我有大约50个网站,在5个Web服务器之间进行负载平衡。它们都使用企业库缓存,并访问相同的缓存数据库。使用ICacheItemRefreshAction实现,每隔几个小时刷新一次缓存数据库中的项目。
我想通过将刷新代码放在critical section中来保证只有一个网站刷新过缓存。
如果网站在单个服务器上的单个应用程序池中运行,则可以使用lock()
如果网站在单个服务器上的不同应用程序池中运行,则可以使用Mutex。
但是,这些将不能确保跨多个Web服务器的关键部分。
当前,我正在缓存数据库中创建一个新密钥来充当互斥体。这通常可以正常工作,但是我看到两个进程可以进入关键部分的机会很小。
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");
}
}
}
有没有一种保证关键部分可以确保我不会两次调用Web服务的方法?
编辑我应该补充一点,我不能使用共享文件,因为部署策略会阻止它。
StackOverflow参考:
Will lock() statement block all threads in the proccess/appdomain?
Sharing cache between multiple web-sites.
最佳答案
您必须涉及一些通用的外部锁获取。例如,SQL中的表t具有一行和一个锁字段,您将在其中获取具有以下内容的锁:
set transaction isolation serializable;
update t set lock = 1 where lock = 0;
检查受影响的行,如果它的1具有锁,则通过将锁更新为0来释放它。这实际上是对SQLServer的行锁的back带,如果两个同时启动,则只有一个在S锁之后将获得U锁,另一个将被阻塞然后返回受影响的0行(因为第一个事务将其翻转为1)。
关于c# - 网络农场中的分布式关键部分,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5354362/