3

5 つの Web サーバー間で負荷分散された約 50 の Web サイトがあります。それらはすべて Enterprise Library Caching を使用し、同じ Caching データベースにアクセスします。キャッシュ データベース内のアイテムは、ICacheItemRefreshAction 実装を使用して、数時間ごとに更新されます。

更新コードをクリティカル セクションに配置することで、1 つの Web サイトのみがキャッシュを更新することを保証したいと考えています。

  • Web サイトが単一のサーバー上の単一のアプリケーション プールで実行されている場合、lock()を使用できます。

  • Web サイトが単一サーバー上の個別のアプリケーション プールで実行されている場合、Mutexを使用できます。

ただし、これらは複数の 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");
        }
    }
}

Web サービスを 2 回呼び出さないように、クリティカル セクションを保証する方法はありますか?

編集展開ポリシーによって禁止されるため、共有ファイルを使用できないことを追加する必要があります。

StackOverflow 参照:

4

2 に答える 2

4

すべてに共通の外部ロック取得を含める必要があります。たとえば、1 つの行と 1 つのロック フィールドを持つ SQL のテーブル t では、次のようにロックを取得します。

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

影響を受ける行を確認し、ロックを持っている場合は、ロックを 0 に更新して解放します。これは、基本的に SQLServer の行ロックに便乗します。2 つが同時に開始された場合、S ロックの後に 1 つだけが U ロックを取得し、もう 1 つがブロックされます。その後、影響を受けた 0 行を返します (最初のトランザクションが 1 に反転したため)。

于 2011-03-18T15:48:01.703 に答える
1

ロック ハンドルを作成/返すためのロジックをデータベースに移動し、それらを結合することをお勧めします。これにより、常に 1 つのプロセスがロックを保持することが保証されます。

そのため、データベースにはロックを要求するストアド プロシージャがあり、空の結果 (失敗) を返すか、レコードを作成して返します。

于 2011-03-18T15:49:20.707 に答える