У меня около 50 веб-сайтов с балансировкой нагрузки на 5 веб-серверах. Все они используют Enterprise Library Caching и имеют доступ к одной и той же базе данных Caching. Элементы в базе данных Caching обновляются каждые несколько часов с использованием реализации ICacheItemRefreshAction.
Я хочу гарантировать, что только один веб-сайт обновляет кеш, поместив код обновления в критическую секцию .
Если бы веб-сайты работали в одном пуле приложений на одном сервере, я мог бы использовать lock ()
Если бы веб-сайты работали в отдельных пулах приложений на одном сервере, я мог бы использовать Mutex .
Однако это не обеспечит критическую секцию между несколькими веб-серверами.
В настоящее время я создаю новый ключ в базе данных кэширования, чтобы действовать как мьютекс. Это будет обычно работать, но я вижу малую вероятность того, что 2 процесса могут войти в критическую секцию.
public class TakeLongTimeToRefresh : ICacheItemRefreshAction
{
#region ICacheItemRefreshAction Members
public void Refresh(string removedKey, object expiredValue, CacheItemRemovedReason removalReason)
{
string lockKey = "lockKey";
ICacheManager cm = CacheFactory.GetCacheManager();
if (!cm.Contains(lockKey))
{
Debug.WriteLine("Entering critical section");
// Add a lock-key which will never expire for synchronisation.
// I can see a small window of opportunity for another process to enter
// the critical section here...
cm.Add(lockKey, lockKey,
CacheItemPriority.NotRemovable, null,
new NeverExpired());
object newValue = SomeLengthyWebserviceCall();
cm.Remove(removedKey);
Utilities.AddToCache(removedKey, newValue);
cm.Remove("lockkey");
}
}
}
Есть ли способ иметь гарантированный критический раздел , чтобы я не вызывал веб-службу дважды?
РЕДАКТИРОВАТЬ Я должен добавить, что я не могу использовать общий файл, так как политики развертывания будут препятствовать этому.
Ссылки StackOverflow: