2016-12-08 10 views
0

私はGuava Cacheを使用してデータをキャッシュします。キャッシュ内のデータは、数分間使用されていなければクリーニングされます。グアバキャッシュの汚れたデータを処理する方法

データを変更した場合、キャッシュ内のデータを更新し、データを「ダーティ」にマークします(変更されるためデータベース内のデータと異なるため)。 5分ごとに、「汚れた」データをデータベースにプッシュします(つまり、データベースのデータを更新します)。

問題は「汚い」データAは、データのデータベースにプッシュされる前に存在し、ある、データAは、最初にクリーニングされた、そして私は、だから、「汚い」データA.

を失うことになりますデータが消去されたらRemovalListenerGuava Cacheに追加します。RemovalListenerは私に気づき、コールバック機能を行います。この関数では、データをキャッシュに戻そうとします。しかし、マルチスレッド環境では、正しいデータを保証することはできません。

例:

1)キャッシュ:クリーンデータ

2)スレッド1:データAを取得し、キャッシュ内のデータAが清掃されたので、キャッシュはdatabase.AndからのデータAを取得しますデータベース内のデータAは最新ではありません。したがって、スレッド1は不正なデータを取得します。

3)キャッシュ:RemovalListenerコールバックを実行します。

このように、汚れたデータをどのように扱うことができますか?マルチスレッドの場合、データは常に正しいと私は約束できますか?ありがとう!

+0

あなたは本当にデータベースの更新をそのように延期する必要がありますか?データベースへのコミットの正常なプロセス(およびそれが通過したことを確認すること)が重すぎますか? – Thilo

+0

@Thiloデータベースを頻繁に更新すると、DB I/Oのパフォーマンスが低下します。私はちょうど5分ごとにデータベースを更新します。 – Gradle

答えて

0

可能な解決策は、汚れたデータをRemovalListenerに書き込むことです。これが同期されると、同じエントリーに対する他の操作はブロックされ、矛盾した状態は見えなくなります。データベースのレイテンシに応じて、これはキャッシュ上の他の操作にも影響する可能性があります(Guavasのドキュメントの警告を参照)。

一般的に言えば、あなたがしたいのは、いわゆる「キャッシュバック」です。この機能を組み込んだキャッシュ製品があります。既存のソリューションを見てみましょう。

+0

ありがとう!しかし、2つの操作(キャッシュのデータを消去)と(RemovalListener)は原子的な操作ではないので、mutithreadでは、質問の例のように問題が発生します。 – Gradle

+0

私はGuavaの専門家ではないことを認めなければなりませんが、同期除去リスナーの感覚は削除と同期して行う必要があることです。なぜそれが原子ではないと思いますか? – cruftex

+0

@curftex申し訳ありませんが、私は同期と原子のパズルをhava。私の意見では、削除は同期的に行われますが、2つの操作(キャッシュのデータ消去)と(RemovalListener)はアトミックではありません。だから私は2つの操作の間で、いくつかのスレッドは、キャッシュから間違ったデータを取得するいくつかの操作を行うだろうと思う。私はそれに困惑した。だからあなたはそれを説明することができます.... – Gradle

関連する問題