3

私は、Azure Shared Cachingを使用して、サーバー側のWebサーバーのキャッシングレイヤーに取り組んでおり、データベースへの要求の量を減らして、処理を高速化します(うまくいけば)。私が立ち往生しているのは、スレッド全体を安全にする方法です。DataCacheでキーをロックするための信頼できる使用可能な方法が見つからないようです。私が見逃しているのは、何かが格納される前にキーを事前にロックする方法です。これにより、別のスレッドが同じことを同時に実行しようとするリスクなしに値を追加できます。

私はこれまで悲観的なロックだけに注目してきました。それがスレッドセーフが私にとって最も理にかなっている方法なので、私が取り組んでいるものがロックされていることを確認したいと思います。

悲観的ロックを使用する場合、私はそれに関連するメソッドのみを使用する責任があることを理解しました。物事を混ぜると、ロックメカニズム全体が台無しになります(ソース:http://go4answers.webhost4life.com/Example/datacacheput-unlocking-key-77158.aspx)。

So basicly I only have access to these methods:
value GetAndLock(key, out DataCacheLockHandle);
void PutAndUnlock(key, value, DataCacheLockHandle);
void Unlock(key, DataCacheLockHandle);

問題は、まだキャッシュにないものを取得しようとすると、「GetAndLock」が例外をスローすることです。同時に、キャッシュに何かを追加するための私の唯一の方法は「PutAndUnlock」であり、「GetAndUnlock」を成功させない限り、その方法を使用することはできません。

事実上、キャッシュに新しいものを追加することは不可能です。実行できるのは、すでに存在するものを置き換えることだけです(これは何もありません)。

したがって、「GetAndLock」が例外をスローしない場合は、楽観的な「Put」を使用せざるを得ないように思われます。しかし、私が読んだことによると、楽観的な「Put」は「GetAndLock」で達成された既存のロックをすべて破壊するため、スレッドセーフの試み全体が破壊されます。

Example plan:
1. Try to GetAndLock
2. In case of nothing there exception: 
     - Put a dummy item on the key. 
     - GetAndLock again.
3. We have a lock, do computations, query database etc
4. PutAndUnlock the computed value


One of probably several ways it would screw up:
Thread1: Tries to GetAndLock, gets nothing there exception
Thread2: Tries to GetAndLock, gets nothing there exception
Thread1: Put a dummy item on the key
Thread1: GetAndLock again, lock achieved
Thread2: Put a dummy item on the key (destroying Thread1:s lock)
Thread2: GetAndLock again, lock achieved
Thread1: We think we have a lock, do computations, query database etc
Thread2: We have a lock, do computations, query database etc
Thread1: PutAndUnlock the computed value (will this throw an exception?)
Thread2: PutAndUnlock the computed value

基本的に、2つのスレッドは、両方が持っていると考えているロックを無視して、同じキーに同時に異なるものを書き込むことができます。

私の唯一の結論は、DataCacheの悲観的なロックは機能が不完全であり、完全に使用できないということです。私は何かが足りないのですか?これを解決する方法はありますか?

私が見逃しているのは、キーに何かが保存される前に、キーを事前にロックする方法だけです。

4

1 に答える 1

0

ジョナサン、

キャッシュに何かを追加するためのこのロジックを考慮しましたか (私の疑似コードを許してください)。

public bool AddToCache(string key, object value) {

DataCache dc = _factory.GetDefaultCache();  
object currentVal = dc.Get(key);

if (currentVal == null) {
    dc.Put(key, value);
    currentVal = dc.GetAndLock(key);

    if (value == currentVal) {
        //handle this rare occurrence + unlock.
        return false;
    } else {
                   dc.Unlock(key);
            }
} else {
    currentVal = dc.GetAndLock(key);
    dc.PutAndUnlock (key, value);
}

return true;

}

于 2013-03-15T02:24:09.523 に答える