2011-03-18 6 views
3

5 개의 웹 서버에 부하가 분산 된 약 50 개의 웹 사이트가 있습니다. 이들은 모두 엔터프라이즈 라이브러리 캐싱을 사용하고 동일한 캐싱 데이터베이스에 액세스합니다. 캐싱 데이터베이스의 항목은 ICacheItemRefreshAction 구현을 사용하여 몇 시간마다 새로 고쳐집니다.웹 팜의 분산 된 중요 섹션

critical section에 새로 고침 코드를 넣으면 웹 사이트 하나만 캐시를 새로 고칠 수 있습니다. 웹 사이트를 하나의 서버에 하나의 응용 프로그램 풀에서 실행중인 경우 웹 사이트 하나에 별도의 앱 풀에서 실행중인 경우

  • , 나는 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"); 
     } 
    } 
} 

있습니까?

EDIT 배포 정책으로 인해 공유 파일을 사용할 수 없다고 추가해야합니다.

StackOverflow의 참조가 :

+0

어떤 종류의 토큰 링 시스템일까요? – jp2code

답변

4

당신은 모두에게 공통의 일부 외부 잠금 acquisiton을 포함해야합니다. 예를 들어, 당신이 잠금 획득 할 하나의 행과 하나 개의 잠금 필드 SQL에서 테이블 t : 영향

set transaction isolation serializable; 
update t set lock = 1 where lock = 0; 

체크 행을 그리고 만약 그 일이 잠금을 0으로 잠금을 업데이트하여 놓습니다. 이것은 본질적으로 SQLServer의 행 잠금에 피기 백합니다. 두 개가 동시에 시작되면 S 잠금 후 U 잠금을 얻고 다른 블록이 차단되어 영향을받은 행이 0 개 (첫 번째 트랜잭션이 1로 바뀌었기 때문에)를 반환합니다.

+0

이것이 올바른 접근이라고 생각합니다. 기존 키를 추가 한 경우 EL 캐싱에서 예외가 발생하면 동일한 효과가 나타납니다. 그러나 그렇지 않으면 SQL로 직접 구현해야합니다.고마워 :) –

+6

이 잠금은 내구성이 없다는 것을 명심하십시오. 프로세스가 획득 한 후에 결함이 있지만 잠금을 해제하기 전에 영구히 잠긴 상태로 유지됩니다. 로그 아웃하는 좋은 방법은 타임 아웃을 강제하는 것입니다. 즉, 잠금이 설정된 시간에 해제되지 않으면 요청자가 lock = 1 인 경우에도 마찬가지입니다. 'set lock = 1, locktime = getdate() where lock = 0 또는 datediff (m, locktime, getdate())> 15 'for 15 분 – mmix

+0

@mmix 제안 해 주셔서 감사합니다. 나는 그것을 사용하고있다. 유일한 문제는 datepart "m"이 몇 분이 아닌 몇 달 동안 있다고 생각합니다. 분은 "mi"가됩니다. 참조 : https://msdn.microsoft.com/en-us/library/ms189794.aspx –

1

잠금 핸들을 생성/반환하는 로직을 데이터베이스로 옮기고 으로 합치면 잠금이 항상 하나의 프로세스로 보장됩니다.

그래서 데이터베이스에 잠금을 요구하는 저장 프로 시저가있을 수 있으며, 빈 결과 (실패)를 반환하거나 레코드를 만들어 반환합니다.