需要の原因
同時実行性の高いビジネス シナリオでは、ほとんどの場合、データベースが同時ユーザー アクセスにとって最も弱いリンクとなります。したがって、リクエストが MySQL などのデータベースに直接アクセスするのではなく、最初に Redis にアクセスできるように、redis を使用してバッファリング操作を実行する必要があります。
このビジネスシナリオは主にRedisキャッシュからのデータ読み出しの問題を解決するもので、通常は以下の図のような流れで業務が行われます。
通常、キャッシュの読み取りステップには問題はありませんが、データベースとキャッシュの更新などのデータ更新が含まれると、キャッシュ (Redis) とデータベース (MySQL) の間でデータの一貫性の問題が発生する傾向があります。
最初に MySQL データベースに書き込んでから Redis キャッシュを削除するか、最初にキャッシュを削除してからデータベースに書き込むかに関係なく、データの不整合が発生する可能性があります。例として:
1. Redis キャッシュが削除され、データベース MySQL に書き込む前に別のスレッドが読み取りを開始し、キャッシュが空であることが判明した場合、データベースからデータを読み取り、キャッシュに書き込みます。 、キャッシュにはダーティなデータが含まれています。
2. ライブラリが最初に書き込まれ、キャッシュが削除される前にライブラリを書き込んでいるスレッドがクラッシュし、キャッシュが削除されなかった場合も、データの不整合が発生します。
書き込みと読み取りが同時に行われ、順序が保証されないため、キャッシュとデータベースの間でデータの不整合が発生します。
如来が解決してくれる?ビジネスコストと技術コストに基づいて選択された、最初は簡単、次に難しい 2 つのソリューションを次に示します。
キャッシュとデータベースの一貫性ソリューション
1. 最初のオプション: 遅延二重削除戦略を採用する
## ライブラリを書き込む前後に redis.del (キー) 操作を実行し、適切なタイムアウトを設定します。 疑似コードは次のとおりです。 public void write(文字列キー、オブジェクトデータ){ redis.delKey(キー); db.updateData(データ); Thread.sleep(500); redis.delKey(キー); } 2. 具体的な手順は次のとおりです。 1) まずキャッシュを削除します 2) データベースを再度書き込みます 3) 500 ミリ秒スリープします 4) 再度キャッシュを削除します では、この 500 ミリ秒はどのように決定され、どのくらいの時間スリープする必要があるのでしょうか? プロジェクトの時間のかかるデータ読み取りビジネス ロジックを評価する必要があります。この目的は、読み取りリクエストが確実に終了し、書き込みリクエストによって読み取りリクエストによって発生したキャッシュされたダーティ データを削除できるようにすることです。 もちろん、この戦略では、Redis とデータベースのマスター/スレーブ間の時間のかかる同期も考慮する必要があります。データ書き込みの最終スリープ時間: データ ビジネス ロジックの読み取りにかかる時間に数百ミリ秒が追加されます。例: 1 秒間スリープします。 3. キャッシュの有効期限を設定します 理論的には、キャッシュの有効期限を設定することは、最終的な整合性を確保するための解決策です。すべての書き込み操作はデータベースの影響を受けます。キャッシュの有効期限に達している限り、後続の読み取りリクエストは自然にデータベースから新しい値を読み取り、キャッシュをバックフィルします。 4. このプランのデメリット 二重削除戦略とキャッシュ タイムアウト設定を組み合わせると、最悪のシナリオはタイムアウト期間内にデータの一貫性がなくなり、リクエストの書き込みにかかる時間も増加します。 2. 2 番目の解決策: 非同期更新キャッシュ (binlog へのサブスクライブに基づく同期メカニズム) 1. 全体的な技術的アイデア: MySQL binlog 増分サブスクリプション消費メッセージ キュー増分データの redis への更新 1) Redis の読み取り: ホットデータは基本的に Redis にあります 2) MySQL の作成: 追加、削除、変更はすべて MySQL 上での操作です。 3) Redis データの更新: Redis に更新するための MySQ データ操作のバイナリログ 2.Redis の更新 1) データ操作は主に 2 つのブロックに分かれています: 1 つがいっぱいです (すべてのデータを一度に Redis に書き込みます) 1 つは増分 (リアルタイム更新) ここで話しているのはインクリメントです。これは、mysql の変更データの更新、挿入、削除を指します。 2) バイナリログを読み取った後、それを分析し、メッセージキューを使用して各ステーションの Redis キャッシュデータをプッシュおよび更新します。 このようにして、MySQL で新しい書き込み、更新、削除などの操作が発生すると、バイナリログ関連のメッセージを Redis にプッシュでき、バイナリログ内のレコードに基づいて Redis が Redis を更新します。 実際、このメカニズムは MySQL のマスター/スレーブ バックアップ メカニズムと非常によく似ています。これは、MySQL のマスター/スレーブ バックアップも binlog を通じてデータの一貫性を実現するためです。 ここでは、canal (Alibaba のオープンソース フレームワーク) を組み合わせて使用し、MySQL の binlog をサブスクライブできます。Canal は、mysql のスレーブ データベースのバックアップ要求を模倣するため、Redis のデータ更新で同じ効果が得られます。 もちろん、ここでのメッセージ プッシュ ツールについては、kafka、rabbitMQ などの他のサードパーティを使用して、Redis へのプッシュ更新を実装することもできます。以上がRedis キャッシュと MySQL データの整合性メソッドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。