3

私はAzureキャッシングが初めてで、1つの問題に直面しています。

最初にシナリオについて簡単に説明します。SQL AzureアプリケーションのDBとして使用しています。待機時間の問題とスロットリングの問題を回避するために、Azure キャッシュ (Web ロールのコロケーション キャッシュ) を使用しています。Azure Caching を使用することで、DB からデータを 1 回だけフェッチし、それをキャッシュに保持して後で使用できるようにします。

キャッシュされたデータを使用しているため、ここでの課題は、DML 操作が実行されるたびに、いつでも SQL Azure DB と Azure キャッシュの間でデータを常に同期させることです。最初にDBを更新し、更新が成功した場合はキャッシュされたデータを無効にすることでこれを行っています。このアプローチは、通常のシナリオではうまく機能します。ただし、同時ユーザーが作業して更新を実行していると、問題があるようです。キャッシュ内のデータを更新する際に、悲観的同時実行モデルを使用しています。ここでは、一時的な再試行ポリシーを使用して再試行を確実に行います (1 秒の固定間隔で 5 回としましょう)。

サンプル コードは次のようになります。

Microsoft.Practices.TransientFaultHandling.RetryPolicy cacheRetryPolicy =
    GetAzureCacheRetryPolicy();

cacheRetryPolicy.Retrying += TransientRetryManager.OnRetrying;  
DataCacheLockHandle handle = null;
cacheRetryPolicy.ExecuteAction(() =>
{
    try
    {
        object obj = cache.GetAndLock(key, TimeSpan.FromSeconds(1), out handle);
        cache.PutAndUnlock(key, value, handle, expirationTime.Value, tags);
    }
    catch (DataCacheException ex)
    {
        if (ex.ErrorCode == DataCacheErrorCode.KeyDoesNotExist)
        {
            cache.Put(key, value, expirationTime.Value, tags);
        }
        else
        { 
            //This means wait till the cache is released. 
            //Throwing from here will allow to retry with Transient 
            //handling retry policy.                           
            throw ex; 
        }
    }
}

ここで、待機回数 (6 としましょう) が再試行回数 (この場合は 5) を超えた場合を考えます。6 番目の順番になるまでに、再試行の試行はすでに終了しているため、最新の更新がある 6 番目の Wait はキャッシュでの更新に失敗します。

この問題を解決するには、キャッシュ キーのロックを取得している間にerrorcodeすべての待機をキューに入れる方法があります。objectlocked

誰でもこのケースを処理する最善の方法を提案できますか?

4

1 に答える 1

0

私が間違っていなければ、キャッシュされた結果はDBに最新のデータを保持していません。

--------------------------------------------------------------------------------
This could happen in following Scenario
--------------------------------------------------------------------------------
Time        User 1                              User 2
1           Updates DB data from A to B         Idle
4           Adding data to cache                Updates DB data from B to C
5           Still adding to cache               Adding data to cache
7           Still adding to cache               caching is done
9           Still adding to cache               current data is C
10          caching is done
11          current data is B (but it should be C)
  1. ユーザー 1 の後にユーザー 2 が更新を開始する
  2. したがって、理想的には、最新のデータはユーザー 2 のものである必要があります
  3. ただし、ユーザー 2 のキャッシュ コードはユーザー 1 のコードより前に完了し、ユーザー 1 のキャッシュ コードが起動されます。
  4. そのため、最新の結果は予期しないユーザー 1 になります。

スレッド ロックを使用して解決できる単一インスタンス アプリケーションの場合、Azure はマルチ インスタンスであり、APP へのヒットが多いため、次のアプローチを実行できます。

最善ではないかもしれませんが、アプリケーションが 6 つの Web サーバーで実行され、75,000 を超えるユーザーがいるこの問題を解決しました。

常に 2 つのデータをキャッシュに保持します

  1. キャッシュする必要があるコンテンツ
  2. 同じコンテンツの DB の LastModified 列の値

キャッシュに新しい値を追加する前に、キャッシュ内の LastModified データが DB 内の日付よりも小さいことを常に確認します。なんらかの理由で、キャッシュされたデータが現在の DB データよりも多い場合、どういうわけか最新の値が既にキャッシュにプッシュされているため、追加しません。

So what we have done is
-----------------------------------------------------------------------------------
Time                User 1                      User 2
-----------------------------------------------------------------------------------
1           Updates DB data from A to B         Idle
4           Adding data to cache                Updates DB data from B to C     
5           still adding to cache               Adding data to cache
7           Still adding to cache               caching is done with last modified date
9           Still adding to cache               current data is C
10          found that cached date is greater than the current
11          skips caching
于 2013-09-25T10:22:07.753 に答える