Является ли кеширование результатов путем запроса каждые 10 секунд плохой идеей? - PullRequest
2 голосов
/ 23 августа 2011

У нас есть ситуация, когда мы вызываем функцию в API, которая довольно дорогая.Давайте назовем это API.ExpensiveCall()

Этот ExpensiveCall() часто вызывается в веб-приложении.Хотя это не заметно для одного пользователя, оно становится заметным, если у вас есть 5 или более пользователей одновременно.

Мы хотим кэшировать эти результаты.Но поскольку API.ExpensiveCall() по сути является для нас черным ящиком, у нас нет способа аннулировать наш кэш, чтобы знать, когда обновлять.

Поэтому мы предложили решение создать службу Windows, которая просто вызывала бы этоAPI.ExpensiveCall() каждые десять секунд, затем сохраняйте результаты в локальной базе данных, которую веб-приложение уже использует.

Таким образом, не имеет значения, если на сайте есть 1 пользователь или более 20 пользователей, ExpensiveCall() вызывается только каждые 10 секунд.Это очень контролируемая нагрузка на внешнюю систему, к которой подключен API.ExpensiveCall().

Проблема

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

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

Я хотел бы спросить вас, действительно ли такой способ кэширования - плохая идея?Вы слышали о других системах, использующих такой метод для кэширования?И если это такая плохая идея, есть ли альтернативные более эффективные способы кэширования результатов системы, когда для вас это черный ящик?

РЕДАКТИРОВАТЬ:

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

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

Ответы [ 5 ]

4 голосов
/ 23 августа 2011

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

То, как эти вещи обычно решаются, идетвот так: всякий раз, когда вам нужны данные от дорогого звонка, вы проверяете кеш.Если его там нет, вы вызываете дорогую функцию и сохраняете данные в кеше, добавляя метку времени.Если это так, то вы проверяете, сколько лет данным (отсюда отметка времени).Если он старше 10 секунд, в любом случае вызовите дорогую функцию и обновите кэш.В противном случае используйте кэшированные данные.Встроенный в ASP.NET API кеша позволяет вам делать все это с минимальными усилиями - просто установите срок действия кеша на 10 секунд, и все будет хорошо.

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

3 голосов
/ 23 августа 2011

Если «это не заметно для одного пользователя», то, возможно, вам следует разрешить первому вызову метода кешировать результаты, а затем очищать кеш каждые X секунд.Таким образом, только один вызов каждые X секунд влияет на производительность.

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

2 голосов
/ 23 августа 2011

Нет ничего принципиально неправильного в использовании временного диапазона (например, 10 секунд) для аннулирования кэша.

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

1 голос
/ 24 августа 2011

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

1 голос
/ 23 августа 2011

Похоже, это может быть одноэтапная операция (например, все запросы будут использовать один и тот же результат операции). Если это так, то это также похоже на то, что можно кэшировать в HttpRuntime.Cache.

var mutex = new Mutex();

public IEnumerable<MyData> GetMyData()
{
  mutex.WaitOne();
  var cache = HttpRuntime.Cache;
  var data = cache["MyData"] as IEnumerable<MyData>;
  if (data == null)
  {
    data = API.ExpensiveCall();
    cache.Add("MyData", data, null, 
      DateTime.Now.AddSeconds(60), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
  }

  mutex.ReleaseMutex();
  return data;
}

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

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