Какой-либо кэш данных asp.net поддерживает второстепенное население записей кэша?

У нас есть управляемый данными веб-сайт ASP.NET, который был записан с помощью стандартного шаблона для кэширования данных (адаптированный здесь из MSDN):

public DataTable GetData()
{
   string key = "DataTable";
   object item = Cache[key] as DataTable;
   if((item == null)
   {
      item = GetDataFromSQL();
      Cache.Insert(key, item, null, DateTime.Now.AddSeconds(300), TimeSpan.Zero;
   }
   return (DataTable)item;
}

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

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

9
задан Yellowfog 1 August 2010 в 16:28
поделиться

3 ответа

Вы должны иметь возможность использовать делегат CacheItemUpdateCallback , который является шестым параметром, который является четвертой перегрузкой для Insert с использованием кэша ASP.NET:

Cache.Insert(key, value, dependancy, absoluteExpiration,
    slidingExpiration, onUpdateCallback);

Должно работать следующее:

Cache.Insert(key, item, null, DateTime.Now.AddSeconds(300),
    Cache.NoSlidingExpiration, itemUpdateCallback);

private void itemUpdateCallback(string key, CacheItemUpdateReason reason,
    out object value, out CacheDependency dependency, out DateTime expiriation,
    out TimeSpan slidingExpiration)
{
    // do your SQL call here and store it in 'value'
    expiriation = DateTime.Now.AddSeconds(300);
    value = FunctionToGetYourData();
}

Из MSDN :

Когда срок действия объекта в кэше истекает, ASP.NET вызывает CacheItemUpdateCallback с ключ для элемента кеша и причина, по которой вы можете захотеть обновить пункт. Остальные параметры этого метод являются выходными параметрами. Вы поставляете новый кешированный элемент и необязательный значения срока действия и зависимости до использовать при обновлении кэшированного элемента.

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

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

Если метод обратного вызова вызывает исключение, ASP.NET подавляет исключение и удаляет кешированный ценность.

Я не тестировал это, поэтому вам, возможно, придется немного повозиться с этим, но он должен дать вам общее представление о том, чего вы пытаетесь достичь.

8
ответ дан 4 December 2019 в 22:26
поделиться

Во-первых, укажите дату, которая вам действительно нужна, в классе бережливого производства (также известном как POCO) вместо этого DataTable hog.

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

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

Да, и SqlCacheDependency печально известен своей ненадежностью и может вызвать безумные обновления вашей системы.

0
ответ дан 4 December 2019 в 22:26
поделиться

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

Поступая таким образом, вы также можете выделить метод GetDataFromSQL в отдельный процесс, скажем, в службу Windows, который запускается каждые пять минут, что должно облегчить "залипание" сайта.


Или...

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

(BTW, главный совет, как сделать ваши намерения более ясными, когда вы помещаете объекты в кэш - в Cache есть константа NoSlidingExpirationNoAbsoluteExpiration), которая более читабельна, чем ваш Timespan.Zero)

0
ответ дан 4 December 2019 в 22:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: