C# web场中的分布式临界截面
我有大约50个网站,负载平衡在5个web服务器上。它们都使用企业库缓存,并访问相同的缓存数据库。使用ICacheItemRefreshAction实现每隔几个小时刷新缓存数据库中的项 我想保证只有一个网站会刷新缓存,方法是将刷新代码放在缓存中C# web场中的分布式临界截面,c#,.net,asp.net,mutex,critical-section,C#,.net,Asp.net,Mutex,Critical Section,我有大约50个网站,负载平衡在5个web服务器上。它们都使用企业库缓存,并访问相同的缓存数据库。使用ICacheItemRefreshAction实现每隔几个小时刷新缓存数据库中的项 我想保证只有一个网站会刷新缓存,方法是将刷新代码放在缓存中 如果网站运行在单个服务器上的单个应用程序池中,我可以使用 如果网站在单个服务器上的单独应用程序池中运行,我可以使用一个 但是,这些将无法确保跨多个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服务两次
编辑我应该补充一点,我不能使用共享文件,因为部署策略会阻止它
堆栈溢出引用:
set transaction isolation serializable;
update t set lock = 1 where lock = 0;
检查受影响的行,如果其1有锁,则通过将锁更新为0来释放它。这实际上是在SQLServer的行锁上进行的,如果两个同时启动,则只有一个在s锁之后获得U锁,另一个将阻塞并随后返回受影响的0行(因为第一个事务将其翻转为1).我建议您将创建/返回锁句柄的逻辑移动到数据库,并将它们组合起来,这将保证始终是一个进程拥有锁
因此,数据库可能有一个存储过程,您可以请求锁定,它要么返回空结果(不成功),要么创建一个记录并返回它。可能是某种令牌环系统?我认为这是正确的方法。如果EL缓存在添加现有密钥时引发异常,则会产生相同的效果。然而,由于它不是,我需要自己在SQL中实现它。谢谢:)请记住,此锁定是不持久的,如果您的进程在获取锁后但在释放锁之前出现故障,它将保持永久锁定。一个很好的解决方法是强制超时,这意味着如果锁没有在设定的时间内释放,请求者可以获得它,即使lock=1,比如locktime=getdate(),lock=0或datediff(m,locktime,getdate())>1515min@mmix谢谢你的建议。我正在用它。唯一的问题是,我认为datepart“m”是几个月,而不是几分钟。分钟是“米”。参考: