Доступ к базе данных в очереди, чтобы избежать нескольких элементов кэша - PullRequest
2 голосов
/ 07 июня 2010

У меня есть связанный с музыкой веб-сайт ASP.NET, который кэширует много статической информации из базы данных при первом запросе.

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

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

Могу ли я использовать блокировку резьбы? Например, я могу сделать что-то вроде lock (this) {доступ к базе данных здесь} ?

Ответы [ 2 ]

3 голосов
/ 07 июня 2010

Да, в вашем кеширующем коде вы захотите поместить свой код доступа к базе данных в блок lock. Однако не блокируйте this. Обычно вы делаете что-то вроде

private static readonly object staticObjectToLockOn = new object();

...

if (cache[cacheKey] == null)
{
   lock(staticObjectToLockOn)
   {
      // double-check the cache is still null inside the lock
      if (cache[cacheKey] == null)
      {
         // get data from the database, add to cache
      }
   }
}
1 голос
/ 07 июня 2010

Смысл использования универсальной блокировки в том, что у вас серьезные проблемы со многими пользователями, поскольку поток может быть заблокирован для каждого элемента кэша при запуске вашего приложения. Более того, каждый поток будет по-прежнему создавать свою собственную блокировку и запрос (и с 10 машинами и 32 потоками каждый, это 320 запросов!)

Мы используем такой подход (> 10 миллионов просмотров страниц в день и memcached):

При получении данных из базы данных мы сохраняем сообщение «в процессе» в аналогичном ключе кэша (например, добавляем in-progress к ключу кэша или чему-то еще). Когда другой поток не может найти текущий элемент, он проверит ключ выполнения. Если элемент в процессе, подождите пару мс. и попробуйте получить снова. Если через несколько секунд (500 мс?) Снова выполнить действие базы данных из текущего потока, чтобы обезопасить себя от уничтожения приложения, когда элемент продолжает работать.

Таким образом, вы можете создать своего рода блокировку, но для нескольких машин и т. Д.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...