Как избежать штормов запросов к базе данных с помощью шаблона кэширования

Мы используем базу данных PostgreSQL и сервер AppFabric, на котором запущен умеренно загруженный сайт электронной коммерции ASP.NET MVC.

Следуя шаблону без кеша, мы запрашиваем данные из нашего кеша, и если они недоступны, мы запрашиваем базу данных.

Этот подход приводит к «шторму запросов», когда база данных получает несколько запросов на одни и те же данные за короткий промежуток времени, в то время как данный объект в кэше обновляется. Эта проблема усугубляется более длительными запросами, и очевидно, что несколько запросов на одни и те же данные могут привести к тому, что запрос будет выполняться дольше, образуя неприятную петлю обратной связи.

Одним из решений этой проблемы является использование блокировки чтения в кэше. Однако это само по себе может вызвать проблемы с производительностью в ситуации с веб-фермой (или даже на одном занятом веб-сервере), поскольку веб-серверы блокируются при чтении без причины, если выполняется запрос к базе данных.

Другим решением является отказ от шаблона кэширования и независимое заполнение кеша. Это подход, который мы использовали, чтобы смягчить непосредственные проблемы, которые мы наблюдаем с этой проблемой, однако это возможно не со всеми данными.

Я что-то упустил здесь? И какие другие подходы люди использовали, чтобы избежать такого поведения?


person jamiecon    schedule 10.03.2011    source источник


Ответы (2)


В зависимости от количества серверов, которые у вас есть, и вашей текущей архитектуры кэша, возможно, стоит также оценить добавление кэша на уровне сервера (или в процессе). По сути, вы используете это как резервный кеш, и это особенно полезно, когда обращение к основному хранилищу (базе данных) либо очень ресурсоемко, либо медленно.

Когда я использовал это, я использовал шаблон отступления от кеша для основного кеша и сквозной дизайн для вторичного кеша, в котором вторичный блокируется и гарантирует, что база данных не перенасыщена одним и тем же запросом. . В этой архитектуре первичный промах кеша приводит не более чем к одному запросу на каждый объект на сервер (или процесс) к базе данных.

Итак, основной рабочий процесс:

1) Попробуйте получить данные из основного/разделяемого кэш-пула

* If successful, return
* If unsuccessul, continue

2) Проверить внутрипроцессный кеш на наличие значения

* If successful, return (optionally seeding primary cache)
* If unsuccessul, continue

3) Получить блокировку по ключу кеша (и перепроверить внутрипроцессный кеш на случай, если он был добавлен другим потоком)

4) Получить объект из основного хранилища (дБ)

5) Семенной внутрипроцессный кеш и возврат

Я сделал это с помощью инъекционных оболочек, все мои слои кеша реализуют соответствующий интерфейс IRepository, а StructureMap внедряет правильный стек кешей. Это сохраняет фактическое поведение кэша гибким, целенаправленным и простым в обслуживании, несмотря на то, что оно довольно сложное.

person STW    schedule 21.08.2013

Мы успешно использовали AppFabric со стратегией заполнения, которую вы упомянули выше. На самом деле мы используем оба решения:

  1. Задайте известные данные, где это возможно (у нас есть ограниченный набор, так что нам на самом деле легко это выяснить)
  2. В каждом методе доступа к кешу обязательно выполняйте обход по мере необходимости и заполняйте кеш при извлечении из хранилища данных.

Это необходимо, так как элементы могут быть удалены из-за нехватки памяти или просто потому, что они были пропущены в операции заполнения. У нас есть «прогревающий» сервис, который пульсирует с интервалом (час) и сохраняет кеш заполненными необходимыми данными. Мы продолжаем анализировать промахи кеша и используем его для настройки нашей стратегии потепления, если мы видим частые промахи в течение интервала потепления.

person Nicolas Webb    schedule 06.04.2011