データベースとキャッシュデュアル書き込み一貫性
今日のアーキテクチャでは、その高い並行性と高いパフォーマンス特性によるキャッシュは、それが広く使用されています。読み取りキャッシュの面では、理由は非常に単純ですが、キャッシュの更新のこの時点では、最終的には論争があり、キャッシュを更新するか、データベースを更新することです。
理論的には、キャッシュの有効期限を設定し、それが最終的なソリューションの一貫性を確保することです。このプログラムでは、我々はキャッシュされたデータの有効期限を設定することができ、すべてのキャッシュの動作が唯一最善を行うことができ、勝つデータベースに書き込みます。これは、データベースが成功したキャッシュの更新が失敗した場合、書き込みすることを意味し、彼らは有効期限に達すると、その後、後続の読取り要求は当然、データベースから新しい値を読み込んでキャッシュバックフィルします。そのため、アイデアの以下の議論は、このプログラムの有効期限にキャッシュ設定に依存しません
三種類のポリシーを更新します
- データベースを更新し、キャッシュを更新するには
- キャッシュを削除し、データベースを更新
- データベースを更新し、キャッシュを削除するには
1. まず、データベースを更新し、キャッシュを更新します
このプログラムは、それらが一般的に反対しています。なぜ?次の2つの理由。
一つの理由(スレッドセーフな角度)
AとBの更新操作要求が、そこであろうが要求
(1)スレッドがデータベースが更新
(2)データベーススレッドBを更新し
(3)Bは、キャッシュスレッドを更新する
(4)スレッドがキャッシュを更新します
キャッシュを更新するためにBの要求よりも早い魚であるように見えますが、ネットワーク上の理由から、Bが先にキャッシュより更新されたキャッシュを更新するための要求。これは、ダーティデータにつながり、そのためと考えられていません。
二つの理由(ビジネスシナリオ角度)
以下の2点があります。
(1)あなたは、データのシーンは、彼らがデータを読み取れない、につながる、このプログラムを使用して、比較的小規模なビジネスニーズをされている読み取り、データベースのシナリオより多くの書き込み、およびされている場合は、キャッシュは、頻繁に廃棄物の性能が更新されます。
(2)データベースの値を書き込む場合は、直接キャッシュを書きますが、複雑な計算を再書き込みキャッシュのシリーズを通過しません。それぞれが、データベースへの書き込みの後にそう、計算された値は、再びキャッシュにパフォーマンスのは間違いない廃棄物を書かれています。明らかに、キャッシュを削除することがより適しています。
次の議論は、最初のキャッシュを削除し、データベースを更新し、最も物議を醸すです。または、データベースを更新し、キャッシュの問題を削除します。
まずキャッシュを削除し、データベースを更新
このプログラムのための理由は、一貫性のないはいにつながります。同時に動作A、他のBリクエストクエリ操作を更新する要求があります。そして、それは次のような状況が表示されます。
(1)書き込み要求を、キャッシュを削除
(2)発見キャッシュクエリ要求不在B
古い値を取得するためにデータベースクエリに要求B(3)
(4)古い値Bの要求はキャッシュを書き込む
(5)新たな要求をデータベースに書き込まれた値
上記の状況は矛盾につながります。キャッシュポリシーの有効期限を設定するために使用されていない場合はさらに、データは常に汚れています。
だから、どのようにそれを解決するには?使用して遅延戦術二重欠失
擬似コード
public void write(String key,Object data){
redis.delKey(key);
db.updateData(data);
Thread.sleep(1000);
redis.delKey(key);
}
説明を中国語に翻訳されます
(1)第1の位相アウトバッファ
(2)書き込みデータベース(元のように、これらの二つのステップは、)
(3)再びキャッシュのうち、1秒スリープ
そうするために、もう一度削除によって引き起こされる1秒でダーティデータをキャッシュすることができます。
さて、どのくらいの特定の睡眠を決定した第2どのようにこの1?
上記のケースでは、読者は自分のプロジェクトのデータのビジネスロジックを読むために自分の時間のかかるを評価する必要があります。ビジネスロジック上の読み出しデータの基礎を消費するスリープ時にデータを書き込むその後、あなたは数百ミリ秒を追加することができます。そうすることの目的は、読み取り要求の終わりには、ダーティデータによって引き起こされるキャッシュされた読み取り要求を削除することができリクエストを書くことを確認することです。
あなたはどのように行うには、別の読み取りおよび書き込みアーキテクチャMySQLを使用している場合は?
[OK]を、この場合は、一貫性のないデータ、または2つの要求、更新操作のAのための1つの要求、他のBリクエストクエリ操作の原因として。
(1)書き込み要求を、キャッシュを削除
(2)データベースにデータを書き込むための要求を、
(3)クエリ要求バッファBが発見された、値バッファ
(4)ライブラリーからの要求Bを照会しないように、この時間は、していませんマスタースレーブの同期が完了したクエリに古い値となるよう、
(5)書き込みキャッシュを要求する古い値B
マスター・データベース同期から(6)が完了すると、ライブラリは新しい値となり、
上記状況、一貫性のないデータの理由です。または二重欠失遅延戦術。しかし、マスタースレーブ遅延時間に基づいて、同期、プラス数百ミリ秒でスリープ時間を変更して。
行うにはどのようにスループットを減らすために、この同期位相アウト戦略とは?
[OK]を、その後、第二非同期として削除します。自分スレッド、非同期で削除します。このように、書かれた要求は、一定期間後に眠る、その後、返さないでしょう。スループットを向上させるために、これを行うには。
削除を行う方法を失敗した場合は、2番目の?
これは、第2の削除が失敗したため、状況が生じることになる、非常に良い質問です。利便性のための2つの要求、更新操作のAのための1つの要求、他のBリクエストクエリ操作は、その単一のライブラリーを想定し、あります。
(1)書き込み要求を、キャッシュを削除
(2)発見キャッシュクエリ要求不在B
古い値を取得するためにデータベースクエリに要求B(3)
(4)古い値Bの要求はキャッシュを書き込む
(5)新たな要求をデータベースに書き込まれた値が
(6)リクエストがキャッシュ削除要求B値への書き込みをしようとし、結果は失敗しました。
OK、それは言うことです。2回目の失敗は、キャッシュを削除した場合は、キャッシュとデータベースの問題が再び矛盾が発生します。
どのようにそれを解決するには?
具体的な解決策は、(3)政策の種類を更新する最初のブロガーを見て解決します。
3.最初の更新のデータベース、およびキャッシュを削除します
まずは、について話しましょう。外国人は「キャッシュ・脇パターン」と呼ばれる、キャッシュ更新ルーチンを作りました。指摘どの
- 失敗:、データキャッシュを取り始めるために得ることはありません、データベースから、成功の後、キャッシュにデータをフェッチするアプリケーション。
- ヒット:復帰後に採取されたキャッシュからのデータへのアプリケーションアクセスを。
- 更新:データベースにデータを入れて、成功した後、キャッシュの無効化をしましょう。
また、ソーシャルネットワーキングサイトFacebookはまた、提案した「フェイスブックでMemcacheのスケーリング」のよく知られた紙である、彼らはまた、データベースを更新し、キャッシュされたポリシーを削除するために使用されています。
この並行性の問題は存在しないのですか?
そうではありません。クエリ要求Aを行うための2つの要求があるだろうと仮定すると、更新操作を行うための要求B、その後、事態が生成されます。
(1)キャッシュがちょうど失敗
(2)古い値を取得するデータベースを照会するための要求を
(3)Bがデータベースに書かれた新しい値を要求
(4)キャッシュされたリクエスト・Bの除去は、
(5)書き込みキャッシュの古い値への要求が見つかりました。
この問題が発生した場合は[OK]を、本当に汚いのデータが発生します。
しかし、この出来事とどのように多くの可能性はありますか?
このステップよりも(3)データベース書き込み動作ステップ先天的条件が存在する発生(2)読み取り、可能な短い時間のかかるデータベース操作は、ステップ(4)の前段階にいること(5)。しかし、私たちが考えて、(読み取りおよび分離、独立した読み取りを書いて、それが読み出し動作より速く、より少ないリソースを消費するので、意味を作ることです書くのですか、他なぜ)のでステップ、およびデータベースの書き込み操作よりもはるかに速いスピードを読んで(3)時間のかかるステップ(2)よりも短く、このような状況が表示されますすることは困難です。
誰かが強迫性障害を持っていると仮定し、どのように行うために解決しなければなりませんか?
どのように並行性の問題を解決するには?
まず、バッファ時間を設定することが効果的なプログラムです。第二に、削除ポリシーの遅延を与え、非同期戦略(2)の使用は、要求の読み取りが完了した後、それを削除することを確認します。
矛盾がそれを引き起こしたため、他の理由がありますか?
はい、これはそれはそれは、一貫性のないと思われる場合ではない、(3)の問題があり、どのようにやっている場合、キャッシュに障害が発生した削除キャッシュ更新ポリシー(2)及びキャッシュ更新ポリシーです。リクエストがデータを書き込み、その後、データベースに書き込まれ、キャッシュに障害が発生した削除する例えば、それは矛盾に表示されます。また、これは、左の最後のキャッシュ更新ポリシーの質問(2)です。
どのように解決するには?
再試行するセーフガードメカニズムを提供し、ここで2つのオプションがあります。
プログラム:
流れは次の通りである
(1)データベースのデータを更新する。
ので、(2)故障したキャッシュの問題を削除する
(3)削除するキーがメッセージ・キューに送信される
(4)削除する独自の消費メッセージ鍵が得られる
(5)。それが成功するまで削除操作を再試行し続けます
しかしながら、この解決策は、サービスラインの侵入コードの多数を引き起こすという欠点を有します。オプションIIと、第2の方式では、サブスクリプション・プログラムは、サブスクリプションデータベースのバイナリログを開始するので、必要な操作を取得します。アプリケーション、プログラムから他の、このサブスクリプション・プログラムからの情報へのアクセスでは、キャッシュ操作を削除します。
オプション2:
(1)データベースの更新データを
(2)動作情報データベースは、バイナリログログに書き込まれます
(3)フィードプログラム所望のデータを抽出し、キー
(4)新しい段落非ビジネスコードは、この情報を取得する
(5)キャッシュされたを削除しようとします操作は、削除が失敗した見つかった
(6)メッセージキューに情報を送信する
リトライ動作におけるメッセージ・キューから検索されたデータの(7)。