Потоковая вставка данных в Postgres через денормализованные таблицы. Часть 3.
Часть 1.
Часть 2.
В прошлый части я писал, что TEMP таблицы не используют Write-Ahead Log. Кроме того, такие таблицы существуют только в рамках текущей сессии. То есть они недоступны, если, например, открыть другое подключение и попытаться прочитать их.
TEMP таблицы и параллелизм
У этих таблиц есть ещё одна особенность. Postgres помечает SELECT для TEMP таблиц как PARALLEL RESTRICTED. Это значит, что при выполнении любых операций SELECT, планировщик не может распараллелить запрос, даже когда это возможно.
Что это значит на практике? Запрос, который при других условиях выполнялся бы параллельно и быстрее, не будет выполнен параллельно. Проверить это просто. Можно выполнить уже знакомый по первой части SELECT с GROUP BY на таблицах разного размера и типа (диаграмма 1).
У обычных и UNLOGGED таблиц при количестве строк от 800к – 900к меняется план выполнения с HashAggregate Seq Scan на Parallel HashAggregate Seq Scan. У TEMP таблиц такого не происходит.
Важно уточнить, что решающим фактором здесь является не количество строк, а общий размер таблицы и стоимость выполнения запроса параллельно. В моём примере именно при 800к – 900к строк таблица достигла такого объёма, при котором планировщик посчитал возможным включить параллельное выполнение.
Настройка параллелизма
Это поведение можно настроить при помощи параметров в таблице pg_settings:
min_parallel_table_scan_size = 1024 x 8 kB – минимальный размер таблицы, при котором может использоваться параллелизм;
min_parallel_index_scan_size = 64 x 8 kB – минимальный размер индекса (если есть), при котором может использоваться параллелизм;
parallel_setup_cost = 1000 – условная стоимость запуска параллельных воркеров (чем выше, тем меньше вероятность использования параллелизма);
parallel_tuple_cost 0.1– условная стоимость передачи одной строки между воркерами.
Зададим значение 0 параметраам min_parallel_table_scan_size, parallel_setup_cost и parallel_tuple_cost, назовём этот режим forced parallelism и повторим замеры на обычной таблице.
Примерно до 60–70 тысяч строк запросы с такими настройками выполняются медленнее, чем при стандартных значениях. Но при большем объёме данных параллелизм становится выгоднее. В результате время выполнения запросов сокращается почти в два раза (диаграмма 2).
Промежуточные выводы
1. Особенность TEMP таблиц не позволяет Postgres выполнять запросы на этой таблице параллельно.
2. Обычные и UNLOGGED таблицы не имеют таких ограничений. И при определённых условиях планировщик выберет параллельное выполнение.
3. Параметры базы данных можно настроить так, чтобы планировщик активнее использовал параллелизм.
Следующая часть будет завершающая на эту тему. В ней я наконец-таки расскажу про влияние индексов.
Часть 1.
Часть 2.
В прошлый части я писал, что TEMP таблицы не используют Write-Ahead Log. Кроме того, такие таблицы существуют только в рамках текущей сессии. То есть они недоступны, если, например, открыть другое подключение и попытаться прочитать их.
TEMP таблицы и параллелизм
У этих таблиц есть ещё одна особенность. Postgres помечает SELECT для TEMP таблиц как PARALLEL RESTRICTED. Это значит, что при выполнении любых операций SELECT, планировщик не может распараллелить запрос, даже когда это возможно.
Что это значит на практике? Запрос, который при других условиях выполнялся бы параллельно и быстрее, не будет выполнен параллельно. Проверить это просто. Можно выполнить уже знакомый по первой части SELECT с GROUP BY на таблицах разного размера и типа (диаграмма 1).
У обычных и UNLOGGED таблиц при количестве строк от 800к – 900к меняется план выполнения с HashAggregate Seq Scan на Parallel HashAggregate Seq Scan. У TEMP таблиц такого не происходит.
Важно уточнить, что решающим фактором здесь является не количество строк, а общий размер таблицы и стоимость выполнения запроса параллельно. В моём примере именно при 800к – 900к строк таблица достигла такого объёма, при котором планировщик посчитал возможным включить параллельное выполнение.
Настройка параллелизма
Это поведение можно настроить при помощи параметров в таблице pg_settings:
min_parallel_table_scan_size = 1024 x 8 kB – минимальный размер таблицы, при котором может использоваться параллелизм;
min_parallel_index_scan_size = 64 x 8 kB – минимальный размер индекса (если есть), при котором может использоваться параллелизм;
parallel_setup_cost = 1000 – условная стоимость запуска параллельных воркеров (чем выше, тем меньше вероятность использования параллелизма);
parallel_tuple_cost 0.1– условная стоимость передачи одной строки между воркерами.
Зададим значение 0 параметраам min_parallel_table_scan_size, parallel_setup_cost и parallel_tuple_cost, назовём этот режим forced parallelism и повторим замеры на обычной таблице.
Примерно до 60–70 тысяч строк запросы с такими настройками выполняются медленнее, чем при стандартных значениях. Но при большем объёме данных параллелизм становится выгоднее. В результате время выполнения запросов сокращается почти в два раза (диаграмма 2).
Промежуточные выводы
1. Особенность TEMP таблиц не позволяет Postgres выполнять запросы на этой таблице параллельно.
2. Обычные и UNLOGGED таблицы не имеют таких ограничений. И при определённых условиях планировщик выберет параллельное выполнение.
3. Параметры базы данных можно настроить так, чтобы планировщик активнее использовал параллелизм.
Следующая часть будет завершающая на эту тему. В ней я наконец-таки расскажу про влияние индексов.
👍4
Потоковая вставка данных в Postgres через денормализованные таблицы. Часть 4.
Часть 1.
Часть 2.
Часть 3.
Заключительная часть серии статей. Сегодня отвечу на вопрос, заданный в 1 части: с каким индексом на stage_table такой запрос отработает быстрее всего:
Ответ
Индекс неважен и результаты одинаковые, так как планировщик всегда выбирает HashAggregate с Seq Scan (диаграмма 1), потому что любой другой алгоритм агрегирования окажется медленнее.
Объяснение
Убедится в том, что Postgres неспроста использует HashAggregate, можно на примере, если добавить к таблице индекс и принудительно отключить HashAggregate с помощью опции enable_hashagg:
С включённым HashAggregate видим знакомую картину (диаграмма 2): HashAggregate с Seq Scan для относительно небольших таблиц и Parallel HashAggregate с Seq Scan для крупных таблиц, даже несмотря на наличие индекса.
С отключённым HashAggregate Postgres выбирает GroupAggregate с Index Only Scan или Group Aggregate с Seq Scan, в зависимости от размера таблицы. Наконец-таки индекс используется, но общая производительность всё равно хуже, чем HashAggregate.
Причины следующие:
1. HashAggregate выполняет один последовательный проход по таблице и считает сумму во внутренней хеш‑таблице. Это минимизирует непоследовательный доступ, и данные попадают в кэш CPU. Для нашей задачи – сгруппировать всё содержимое таблицы – это идельный сценарий.
2. Index Only Scan медленнее из-за непоследовательного доступа. Поскольку индекс по умолчанию – это B-Tree, его чтение сопряжено с чтением данных из разных частей памяти. Индексы хороши, когда нужно получить небольшой кусочек таблицы, но не когда нужно обработать всё сразу.
3. GroupAggregate с Seq Scan требует отсортированного входа по ключам, используемым в GROUP BY. Поскольку Seq Scan, который в нашем случае ещё и выполняется параллельно, не гарантирует порядок данных, то планировщик добавляет в план сортировку. Очевидно, это ухудшает время выполнения.
Выводы
Если нужно быстро загрузить большой объём данных в Postgres с использованием промежуточных таблиц, то:
1. Не используйте индексы в промежуточных таблицах, потому что
- вы потратите время на создание индекса;
- индексы замедляют вставку в таблицу;
- индексы не дают преимуществ, если требуется агрегировать данные по всей промежуточной таблице;
2. Используйте UNLOGGED таблицы, вместо TEMP таблиц. Оба типа не используют Write-Ahead Log, но UNLOGGED позволяет распараллеливать запросы SELECT, что может значительно ускорить выполнения запросов. Главное не забыть удалить UNLOGGED таблицу в конце транзакции. Они не удаляются автоматически, как TEMP таблицы.
Важно помнить, что всё вышесказанное верно для рассматриваемого сценария: массовая вставка с последующей агрегацией по всей промежуточной таблице. Для CRUD функционала лучше использовать обычные таблицы и добавлять индексы.
Часть 1.
Часть 2.
Часть 3.
Заключительная часть серии статей. Сегодня отвечу на вопрос, заданный в 1 части: с каким индексом на stage_table такой запрос отработает быстрее всего:
select resource, billing_date, sum(cost)
from stage_table
group by resource, billing_date
Ответ
Индекс неважен и результаты одинаковые, так как планировщик всегда выбирает HashAggregate с Seq Scan (диаграмма 1), потому что любой другой алгоритм агрегирования окажется медленнее.
Объяснение
Убедится в том, что Postgres неспроста использует HashAggregate, можно на примере, если добавить к таблице индекс и принудительно отключить HashAggregate с помощью опции enable_hashagg:
create index idx_billing_data
on billing_data (resource, billing_date)
include (cost);
set enable_hashagg = off;
С включённым HashAggregate видим знакомую картину (диаграмма 2): HashAggregate с Seq Scan для относительно небольших таблиц и Parallel HashAggregate с Seq Scan для крупных таблиц, даже несмотря на наличие индекса.
С отключённым HashAggregate Postgres выбирает GroupAggregate с Index Only Scan или Group Aggregate с Seq Scan, в зависимости от размера таблицы. Наконец-таки индекс используется, но общая производительность всё равно хуже, чем HashAggregate.
Причины следующие:
1. HashAggregate выполняет один последовательный проход по таблице и считает сумму во внутренней хеш‑таблице. Это минимизирует непоследовательный доступ, и данные попадают в кэш CPU. Для нашей задачи – сгруппировать всё содержимое таблицы – это идельный сценарий.
2. Index Only Scan медленнее из-за непоследовательного доступа. Поскольку индекс по умолчанию – это B-Tree, его чтение сопряжено с чтением данных из разных частей памяти. Индексы хороши, когда нужно получить небольшой кусочек таблицы, но не когда нужно обработать всё сразу.
3. GroupAggregate с Seq Scan требует отсортированного входа по ключам, используемым в GROUP BY. Поскольку Seq Scan, который в нашем случае ещё и выполняется параллельно, не гарантирует порядок данных, то планировщик добавляет в план сортировку. Очевидно, это ухудшает время выполнения.
Выводы
Если нужно быстро загрузить большой объём данных в Postgres с использованием промежуточных таблиц, то:
1. Не используйте индексы в промежуточных таблицах, потому что
- вы потратите время на создание индекса;
- индексы замедляют вставку в таблицу;
- индексы не дают преимуществ, если требуется агрегировать данные по всей промежуточной таблице;
2. Используйте UNLOGGED таблицы, вместо TEMP таблиц. Оба типа не используют Write-Ahead Log, но UNLOGGED позволяет распараллеливать запросы SELECT, что может значительно ускорить выполнения запросов. Главное не забыть удалить UNLOGGED таблицу в конце транзакции. Они не удаляются автоматически, как TEMP таблицы.
Важно помнить, что всё вышесказанное верно для рассматриваемого сценария: массовая вставка с последующей агрегацией по всей промежуточной таблице. Для CRUD функционала лучше использовать обычные таблицы и добавлять индексы.
👍4
Иду на AI-хакатон в Белграде от Yandex и Reputeo
На следующей неделе, 21 — 23 ноября, в Белграде пройдёт хакатон, в котором мы с товарищем участвуем. Сейчас ищем в команду ещё двух человек:
- ML/LLM/AI Engineer (RAG, tool calling, LLM stability, prompting, MCP).
- Product Manager (сформулировать проблему и скоуп, нарисовать user flow, уметь в UI/UX).
Какие навыки конкретно потребуются пока не знаем: описания челленджей ещё нет. Хорошо, если вы T-shaped и разбираетесь в смежных областях.
Формат хакатона:
- Старт в пятницу, 17:30. Окончание в воскресенье, 14:00.
- Локация: офис Yandex на Bulevar vojvode Bojovića 12.
- Площадка открыта всю ночь. Можно уехать ночевать домой или остаться - места для отдыха есть.
- Организаторы обеспечивают питание, снеки, напитки.
- Основной язык для коммуникаций с оргами и для презентаций - английский.
- Результаты работы команд будут выложены в open source.
Если вы в Белграде и вам интересно — пишите в лс.
--
P.S. После завершения обязательно расскажу, как всё прошло. Пишите вопросы, если хочется узнать что-то конкретное — постараюсь разузнать в процессе.
На следующей неделе, 21 — 23 ноября, в Белграде пройдёт хакатон, в котором мы с товарищем участвуем. Сейчас ищем в команду ещё двух человек:
- ML/LLM/AI Engineer (RAG, tool calling, LLM stability, prompting, MCP).
- Product Manager (сформулировать проблему и скоуп, нарисовать user flow, уметь в UI/UX).
Какие навыки конкретно потребуются пока не знаем: описания челленджей ещё нет. Хорошо, если вы T-shaped и разбираетесь в смежных областях.
Формат хакатона:
- Старт в пятницу, 17:30. Окончание в воскресенье, 14:00.
- Локация: офис Yandex на Bulevar vojvode Bojovića 12.
- Площадка открыта всю ночь. Можно уехать ночевать домой или остаться - места для отдыха есть.
- Организаторы обеспечивают питание, снеки, напитки.
- Основной язык для коммуникаций с оргами и для презентаций - английский.
- Результаты работы команд будут выложены в open source.
Если вы в Белграде и вам интересно — пишите в лс.
--
P.S. После завершения обязательно расскажу, как всё прошло. Пишите вопросы, если хочется узнать что-то конкретное — постараюсь разузнать в процессе.
👍6
🥉 Мы взяли 3 место!
Закончился хакатон от Yandex и Reputeo, и наша интернациональная команда заняла 3 место. Было сделано сильное, технологичное и полностью рабочее решение — мы этим гордимся.
За 36 часов мы:
- Обработали десятки миллионов постов и комментариев Reddit, отобрав самые залайканные или обсуждаемые треды.
- На этом датасете дообучили RoBERTa-base для предсказания «вирусности» текста.
- Сделали REST API на .NET 8, который принимает текст, генерирует до 250 потенциально лучших вариантов при помощи GPT-5, вызывает RoBERTa для ранжирования и возвращает самый «вирусный» вариант с объяснениями, почему он лучше.
- Собрали адаптивный UI на React: исходный текст, улучшенный текст и наглядную разницу между ними.
- Настроили CI/CD с автоматической сборкой и деплоем фронта и бэкенда на VM.
- Развернули полноценный работающий демо-сайт, доступный по ссылке viraly.site.
Мы были единственной командой, которая сделала не просто очередной враппер для ChatGPT, а построила приложение с кастомной дообученной LLM. И одной из немногих, у кого был полностью работоспособный продукт доступный онлайн.
Возможно, нам немного не хватило продуктовой подачи, чтобы лучше раскрыть инвесторам потенциал того, что мы построили.
Закончился хакатон от Yandex и Reputeo, и наша интернациональная команда заняла 3 место. Было сделано сильное, технологичное и полностью рабочее решение — мы этим гордимся.
За 36 часов мы:
- Обработали десятки миллионов постов и комментариев Reddit, отобрав самые залайканные или обсуждаемые треды.
- На этом датасете дообучили RoBERTa-base для предсказания «вирусности» текста.
- Сделали REST API на .NET 8, который принимает текст, генерирует до 250 потенциально лучших вариантов при помощи GPT-5, вызывает RoBERTa для ранжирования и возвращает самый «вирусный» вариант с объяснениями, почему он лучше.
- Собрали адаптивный UI на React: исходный текст, улучшенный текст и наглядную разницу между ними.
- Настроили CI/CD с автоматической сборкой и деплоем фронта и бэкенда на VM.
- Развернули полноценный работающий демо-сайт, доступный по ссылке viraly.site.
Мы были единственной командой, которая сделала не просто очередной враппер для ChatGPT, а построила приложение с кастомной дообученной LLM. И одной из немногих, у кого был полностью работоспособный продукт доступный онлайн.
Возможно, нам немного не хватило продуктовой подачи, чтобы лучше раскрыть инвесторам потенциал того, что мы построили.
👍18
В С# 14 появился новый синтаксис расширений (extension members), позволяющий добавлять методы, свойства и даже перегружать операторы для существующих типов без создания врапперов и без изменения исходных типов.
Благодаря этому, стал возможен код как на обложке.
Выглядит, мягко говоря, необычно. Давайте разберёмся, что тут вообще происходит…
Читать полностью тут:
- Habr [Ru].
- Blog [Ru].
- Blog [En].
upd: Поддержите плюсами статью на Хабре 👉👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
yet another dev
Я не могу остановиться. Вот вам ещё F#-like кода на C#.
👍9👎3
Read on website.
И до нас дошла ИИ истерия – мы внедрили агента в FinOps дашборд, о котором я рассказывал в течение этого года.
Несмотря на неоднозначное отношение к ИИ в обществе, конкретно это применение ИИ я считаю действительно полезным. Но обо всём по порядку.
Зачем агент в дашборде
Агент способен делать аналитику быстрее, чем человек. Представьте, вместо того чтобы аналитику вручную крутить таблицы, анализируя траты, любой пользователь приложения может спросить обычным человеческим языком ИИ-агента и получить ответ на таком же человеческом языке.
К примеру, менеджер может задать вопрос: “Почему у нас был резкий скачок трат в октябре 2025 года?”. Сколько времени будет потрачено, если поручить эту задачу человеку? Несколько десятков минут? Или несколько часов? ИИ-агент может подготовить аналитику меньше чем за минуту. Но чтобы агент мог это делать, ему нужно уметь ходить в базу данных и для этого есть MCP-серверы.
Как работает агент и что такое MCP
Главная часть, связывающая приложение с агентом, – это MCP (Model Context Protocol), специальный интерфейс, с которым может работать агент.
Проще всего думать об MCP как о REST API для ИИ. Вместо привычного UI-клиента у вас LLM, а вместо контроллеров — «инструменты» MCP-сервера. Агент видит список инструментов и сам решает, какой инструмент вызвать, подставляя аргументы и обрабатывая ответ.
В качестве инструментов может быть что угодно: функция, которая отправляет запросы к базе данных, любой API и так далее. Разработчики библиотек уже делают MCP-серверы вокруг своих продуктов, чтобы агенты в наших IDE могли получать самую свежую информацию об их использовании. Например, есть MCP-серверы для Next.js, Chakra UI, RSuite.
Архитектура решения и жизненный цикл запроса
На диаграмме показано, как проходит типичный запрос.
1. Пользователь задаёт вопрос.
2. Бэкенд добавляет к нему системный промпт (кто такой агент, с какими данными он работает, какие у него ограничения) и отправляет диалог агенту с включённым MCP.
3. Агент анализирует вопрос, выбирает нужный инструмент MCP, генерирует SQL-запрос и отправляет его на MCP-сервер.
4. MCP-сервер выполняет SQL в базе от имени read-only пользователя и возвращает результат.
5. Агент интерпретирует данные, формирует ответ и бэкенд отдаёт его пользователю.
Настройка агента и безопасность
1. Если планируете использовать сторонний MCP-сервер, то обязательно проверьте его на наличие уязвимостей. Например, MCP-сервер для Postgres от Anthropic какое-то время имел уязвимость к SQL инъекциям.
2. Выдавайте для MCP-сервера доступ только на чтение и только на те данные, которые нужны для выполнения задачи. В идеале, это должно быть сделано на уровне привилегий пользователя, который будет использоваться в MCP-сервере.
3. Подбирайте reasoning (способность модели анализировать информацию), отвечающий вашим требованиям. Чем выше reasoning, тем осмысленнее будут ответы модели, но тем дольше будет обрабатываться запрос. Мы используем GPT-5 mini и дефолтный reasoning приводил к тому, что запросы обрабатывались около полуминуты. Для нас это было слишком долго, поэтому мы снизили до низкого уровня. Этого оказалось достаточно для генерации SQL-запросов.
4. В системном промпте максимально подробно объясняйте схему БД, типы данных, примеры запросов, формат для результатов и так далее. Существующие LLM могут ошибиться, извлечь не те данные или неправильно их интерпретировать.
5. Приготовьтесь к тому, что, скорее всего, вам придётся городить костыли. Все инструменты и библиотеки связанные с MCP сырые. Например, нам пришлось запускать MCP-сервер в одном контейнере с приложением, потому что он поддерживает только stdio.
Заключение
С технической стороны реализация аналогичного приложения достаточно проста – это обычный враппер над GPT с MCP-сервером и read-only доступом к БД. Но даже такое приложение способно экономить человеко-часы – агент сильно сокращает путь от вопроса до первых цифр. Теперь ответы на такие вопросы можно получить уже через минуту. Главное не доверять слепо ИИ и перепроверять результаты.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Я знаю, что большинство моих читателей – .NET-инженеры, но, возможно, среди вас есть, как и я, фуллстеки, а может и фронтенд-инженеры. У меня есть небольшой pet-проект на Next.js, и для меня эта история очень актуальна, хоть и обошла стороной. Но хочу предупредить остальных и коротко рассказать про то, что сейчас обсуждают в мире React.
Что случилось
3 декабря в React, а точнее в React Server Components (RSC), обнаружили критическую уязвимость, получившую название React2Shell. Она позволяет удалённо выполнять произвольный код на сервере.
Wiz пишет, что под угрозой 39% облачных сред:
Wiz data indicates that 39% of cloud environments contain instances of Next.js or React in versions vulnerable to CVE-2025-55182 and/or CVE-2025-66478.
Уязвимости присвоили рейтинг 10.0 (наивысший) по шкале CVSS:
1. Для взлома не требуется авторизация и подготовительные шаги.
2. Уязвимы Next.js приложения на React 19 с App Router.
3. Для выполнения вредоносного кода достаточно одного HTTP-запроса.
Более подробный технический разбор уязвимости можно почитать в статье Datadog.
Страшилки
На Reddit множество историй от людей, чьи сервера пытались взломать или уже взломали:
1. The vulnerability is not a joke, you should upgrade asap.
У автора есть несколько Next.js приложений. Он обновил их до патченной версии, но через несколько часов увидел в логах реальные попытки эксплуатации уязвимости.
2. I Got Hacked - And Traced How Much Money Hacker Made.
У этого разработчика на Hetzner крутилось Next.js приложение в Docker. Из-за уязвимости контейнер превратили в криптомайнер. Он потом разобрал скрипты, нашёл крипто-кошелёк злоумышленников и выяснил, что они зарабатывают всего несколько долларов в день.
3. I got hacked - 10+ apps/projects and 3 servers were affected.
У этого автора положили больше десяти приложений и три сервера. Хакеры установили майнеры, зашифровали файлы и оставили записку с выкупом.
4. My NextJS server was compromised by React CVE-2025-55182 exploitation & multi-stage "Meshagent" malware.
У другого разработчика взломали сервер на DigitalOcean. Он получил уведомление о DDoS, а при расследовании нашёл сразу несколько вирусов: RAT, сборщик ключей, DDoS-ботнет и недозапустившийся майнер. Атака произошла буквально в течение суток после публикации информации об уязвимости.
5. Have I been hacked?
Здесь разработчик просто хотел обновить Next.js и внезапно обнаружил у себя в проекте файлы xmrig-6.24.0 и скрипт sex. sh на Hetzner. Комьюнити объяснило, что это следы того же эксплойта.
Как пропатчить
Vercel выпустил утилиту, которая находит уязвимые версии пакетов и обновляет их до безопасных:
npx fix-react2shell-next
Она проверит package.json и предложит обновить next и связанные RSC-пакеты до рекомендованных версий.
Заключение
Мой pet-проект на Next.js пока никто не ломал. Он, к счастью, даже ещё не задеплоен и уже пропатчен. Но эта ситуация – очередное напоминание, что мерами безопасности лучше не пренебрегать.
Please open Telegram to view this post
VIEW IN TELEGRAM
✍6
Ваш кэш в .NET не защищён от cache stampede
У вас есть запрос к базе данных или к платному API, и вы кэшируете результат? Для кэша используете ConcurrentDictionary или MemoryCache?
У кэша, построенного на этих классах, есть одна неприятная проблема: отсутствие защиты от давки кэша (cache stampede). При определённой нагрузке кэш будет многократно выполнять один и тот же запрос из-за отсутствия координации между потоками и репликами. В этой статье я наглядно покажу, как давка кэша влияет на C# приложение и что с этим делать.
Читать на Хабр.
English version.
У вас есть запрос к базе данных или к платному API, и вы кэшируете результат? Для кэша используете ConcurrentDictionary или MemoryCache?
У кэша, построенного на этих классах, есть одна неприятная проблема: отсутствие защиты от давки кэша (cache stampede). При определённой нагрузке кэш будет многократно выполнять один и тот же запрос из-за отсутствия координации между потоками и репликами. В этой статье я наглядно покажу, как давка кэша влияет на C# приложение и что с этим делать.
Читать на Хабр.
English version.
👍6
yet another dev
Ваш кэш в .NET не защищён от cache stampede У вас есть запрос к базе данных или к платному API, и вы кэшируете результат? Для кэша используете ConcurrentDictionary или MemoryCache? У кэша, построенного на этих классах, есть одна неприятная проблема: отсутствие…
В продолжение темы с распределённым кэшем.
Во FusionCache появился функционал распределённой защиты от давки кэша (Distributed Cache Stampede Protection). Работает пока только с Redis.
Подробности можно почитать в релизе.
Во FusionCache появился функционал распределённой защиты от давки кэша (Distributed Cache Stampede Protection). Работает пока только с Redis.
Подробности можно почитать в релизе.
👍6
В этом году вас, читателей, стало заметно больше, и это очень радует. В Telegram теперь 234 (+59) подписчика, в LinkedIn — 272 (+271), на Хабре — 14.
Суммарно по всем соцсетям посты прочитали несколько сотен тысяч человек. Большое вам спасибо за интерес, реакции и обсуждения.
В новом году, как и прежде, буду публиковать собственный, уникальный контент связанный с .NET, C# и разработку в целом. Я по-прежнему стараюсь не повторять ни за кем и рассказывать только о том, с чем работал сам, с какими проблемами сталкивался и как их решал. Чтобы это было полезно вам и другим инженерам.
В новом году всем желаю прод без багов, стабильного перфоманса без деградаций, понятных требований и отсутствие упавших тестов.
Увидимся в 2026 🎄
Please open Telegram to view this post
VIEW IN TELEGRAM
🎄12👏3