トランザクションの多い分散アプリケーションの開発に伴い、パフォーマンスのスケーラビリティを実現するために分散キャッシングソリューションが非常に望まれるようになりました。 NCache インメモリ分散データストアとしては、 線形スケーラビリティ および 高可用性.
ここまでは問題ありませんが、このような共有環境でデータの整合性をどのように確保するかが重要です。 2 つ以上のクライアントがアプリケーション内で同時に同じデータにアクセスして変更できるため、結果としてデータが不整合になる可能性があります。データの整合性違反が発生すると、キャッシュ内のデータは事実上役に立たなくなります。
このブログ投稿では、この問題がどのように発生し、どのように発生するかを説明します NCache そのであなたを救う 分散ロック 特徴。
NCache 詳細 NCache ロッキング Ncache ドキュメント
ロックせずにデータの整合性の問題
データの整合性の問題を詳細に理解するために、オンラインのEコマースストアの例を考えます。このストアでは、売り手が商品をアップロードし、顧客がそれらの商品を表示して注文します。
顧客が特定の製品を表示したいと考えており、その製品の販売者がその価格を更新したいとします。 これで、顧客がより高い価格で製品を表示していて、売り手がユーザーがまだ見ることができない割引を追加した場合、ユーザーはより高い価格で製品を購入することになります。
シナリオを図1に示します。
- クライアント1は、キャッシュ内の製品の詳細を読み取ります。
- クライアント2は製品データも読み取ります。 合ってます。
- クライアント1は、キャッシュ内の製品の詳細を更新するようになりました。
- クライアント2は、キャッシュ内の製品の詳細も更新します。
- クライアント1によって行われた更新は失われます。
方法を見てみましょう NCache この問題を解決します。
NCache 分散ロック
NCache データをロックできるようにすることで、ビジネスニーズに応じてデータを柔軟に保護する方法を提供します。 XNUMX人のユーザーがデータのチャンクを制御し、それを更新します。 その間、他のユーザーはそのデータを操作できません。
アプリケーションシナリオに基づいて、これらのいずれかを選択できます NCache ロックメカニズム:
- 悲観的ロック (トランザクションロックまたは排他ロック):アイテムを排他的にロックして、他のユーザーがアクセスできないようにします。
- 楽観的ロック (アイテムのバージョン管理を介してロック):他のユーザーがアイテムにアクセスできるようにするアイテムのバージョン管理を使用します。
機密データの悲観的ロック
あなたは使用する必要があります 悲観的なロック戦略 アプリケーション内で更新が必要なデータが機密性の高い場合。 LockHandle を使用して、データの明示的なロックを取得できます。完了するとロックが解除されます。
今、私たちはその方法を見る NCache 悲観的ロックは、この例のデータ整合性の問題を解決します。 その間、製品の排他ロックを取得して更新することができますが、他のユーザーはその製品にアクセスできません。 これを図2に示します。
- クライアント 1 は製品のロックを取得し、製品の詳細の追加と更新を開始します。
- クライアント 2 は製品の詳細を読み取るためのアクセスを拒否され、ロックが解除されるまで待つ必要があります。
- ロックが解除されると、クライアント2は製品の通常の操作を続行できます。
注意することが重要です、 NCache ロックありとロックなしのXNUMXセットのAPIをサポートします。 ユーザーが悲観的ロックを使用したい場合は、強力なデータ整合性が必要なアプリケーションのあらゆる場所で、ロックパラメーターを備えたAPIを使用する必要があります。 あなたがそれをどのように行うことができるか見てみましょう NCache ロック機能。 次のコードセグメントでは、最初に新しいLockHandleが作成され、次にタイムスパンが設定されて、ロックが取得される期間が指定されます。 このLockHandleは、ロックを識別するためのロックIDとして機能します。 次に、キーとLockHandleを指定したGetメソッドを使用してロックを取得します。
これで、ビジネスオペレーションを実行し、手動でロックを解除するか、タイムスパンが終了するのを待つことができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// Pre-condition: Cache is already connected // Create a new lock handle to fetch an Item using locking LockHandle lockHandle = new LockHandle(); // Timespan for which lock is to be taken TimeSpan timeSpan = TimeSpan.FromSeconds(5); // Get item from the cache and lock it var result = cache.Get(key, true, timeSpan, ref lockHandle); // Verify if the item is locked successfully if (result != null) { // Item has been successfully locked } else { // Key does not exist // Item is already locked with a different LockHandle } //Unlock item in cache manually cache.Unlock(key, lockHandle); |
ここで、ロックパラメータを使用したGet APIは、ロックの取得を待たずにすぐに戻ります。 そもそも失敗した場合に備えて、アイテムのロックを取得するには、明示的な再結合を行う必要があります。
LockHandleをキーに関連付けるLockメソッドを使用してロックを取得することもできます。 NCache にさまざまな方法を提供します 明示的なロックを取得/解放する これにより、柔軟なロックが可能になります。 実装する場合 NCache ロック、を使用して NCache アイテムをロックするためのサンプルアプリケーション GitHubの 参考になります。
データ可用性のための楽観的なロック
ペシミスティックロックは優れていますが、アプリケーションにとって応答時間が重要な場合は、最適なアプローチではない可能性があります。 ここで、楽観的なロックが役立ちます。
NCache 楽観的なロックの使用 キャッシュアイテムのバージョン管理 明示的なロックの場合に発生するスレッドの枯渇を克服するため。 したがって、そのアイテムを更新するたびに増分される、キャッシュされたアイテムのバージョンで作業できます。 NCache アイテムのバージョンを追跡し、データの一貫性について心配する必要はありません。
図3は、その方法を示しています。
- クライアント1は製品に関する詳細を追加し、CacheItemVersionはv1に設定されます。
- クライアント2は、CacheItemVersionv1を使用して更新された製品の詳細を読み取ります。
- クライアント1は、CacheItemVersionがインクリメントされ、v2になるため、詳細を再度変更します。
- これで、クライアント2が古いCacheItemVersion v1を使用して詳細を更新しようとすると、CacheItemVersionで操作が失敗します。
- クライアント2は最新のCacheItemVersionを取得します
- クライアント 2 は、CacheItemVersion を使用して製品の詳細を更新します。これで操作は正常に実行され、CacheItemVersion が自動的に 1 ずつ増加します。
これにより、すべてのユーザーが常にCacheItemVersionを更新し、ストア内の製品へのアクセスを拒否されるユーザーがいないことが保証されます。
次のコードは、その方法を示しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// Specify the key of the cacheItem string key = "Product:1001"; // Initialize the cacheItemVersion CacheItemVersion version = null; // Get the cacheItem previously added in the cache with the version CacheItem cacheItem = cache.GetCacheItem(key, ref version); // If result is not null if (cacheItem != null) { // CacheItem is retrieved successfully with the version var prod = cacheItem.GetValue(); prod.Discount = 0.5; // Create a new cacheItem with updated value var updateItem = new CacheItem(prod); //Set the itemversion. This version is used to compare the // item version of the cached item updateItem.Version = version; //Insert call will fail with LockingException, if cache contains a newer version of the cache item. //In case of LockingException, we can fetch the latest cache item from cache and update it cache.Insert(key, updateItem); // If it matches, the insert is successful, otherwise it fails } |
なぜ使うの? NCache ロッキング
安全で一貫性のあるデータは、今日のビジネスにとって非常に重要であり、マルチユーザートランザクションのような単純なものがデータの整合性を損なう場合は残念です。
NCache 高度に分散された環境で、最大限の柔軟性を備えたデータの整合性と一貫性を保証します。 アプリケーションシナリオに基づいて、によって提供されるさまざまな方法でさまざまなロックメカニズムを採用できます。 NCache。 最終的には、データの不整合なしに同時実行性が得られます。
あなたが持っている素晴らしい情報を他の人に伝えましょう。 お知らせいただきありがとうございます。 私たちの財産の安全を確保するために、そのような情報を共有し続けてください。