C# web场中的分布式临界截面

C# web场中的分布式临界截面,c#,.net,asp.net,mutex,critical-section,C#,.net,Asp.net,Mutex,Critical Section,我有大约50个网站,负载平衡在5个web服务器上。它们都使用企业库缓存,并访问相同的缓存数据库。使用ICacheItemRefreshAction实现每隔几个小时刷新缓存数据库中的项 我想保证只有一个网站会刷新缓存,方法是将刷新代码放在缓存中 如果网站运行在单个服务器上的单个应用程序池中,我可以使用 如果网站在单个服务器上的单独应用程序池中运行,我可以使用一个 但是,这些将无法确保跨多个web服务器的关键部分 目前,我正在缓存数据库中创建一个新密钥,作为互斥对象。这通常会起作用,但我认为两个

我有大约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服务两次

编辑我应该补充一点,我不能使用共享文件,因为部署策略会阻止它

堆栈溢出引用:


您必须涉及一些所有人都通用的外部锁获取。例如,SQL中具有一行和一个锁定字段的表t,在该表中,您将获得一个具有以下内容的锁定:

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”是几个月,而不是几分钟。分钟是“米”。参考: