我有大约50个网站,在5个网络服务器上进行负载均衡。它们都使用Enterprise Library Caching,并访问相同的Caching数据库。使用ICacheItemRefreshAction实现,每隔几个小时刷新缓存数据库中的项目。
我想保证只有一个网站通过将刷新代码放在critical section中来刷新缓存。
但是,这些不能确保跨多个Web服务器的关键部分。
目前,我正在缓存数据库中创建一个新密钥以充当互斥锁。这将通常工作,但我可以看到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引用:
答案 0 :(得分:4)
你必须涉及一些共同的外部锁定。例如,SQL中的表t包含一行和一个锁定字段,您将获得锁定:
set transaction isolation serializable;
update t set lock = 1 where lock = 0;
检查受影响的行,如果它有1个你有锁,则通过将lock更新为0来释放它。这基本上搭载SQLServer的行锁定,如果两个同时启动,只有一个在S锁定后获得U锁定,另一个一个将阻止并随后返回受影响的0行(因为第一个事务将其翻转为1)。
答案 1 :(得分:1)
我建议您将创建/返回锁定句柄的逻辑移动到数据库并合并它们,这将保证它始终是一个具有锁定的进程。
因此,数据库可能有一个存储过程,您要求锁定,并且它将返回空结果(不成功)或将创建一个记录并将其返回。