Redis はキャッシュの不整合の問題をどのように解決しますか?

WBOY
リリース: 2022-02-25 17:20:45
転載
2522 人が閲覧しました

この記事では、Redis がキャッシュの不整合の問題をどのように解決するか、およびキャッシュとデータベースの間でデータの不整合がどのように発生するかを説明します。一緒に見てみましょう。皆さんのお役に立てれば幸いです。 . .

Redis はキャッシュの不整合の問題をどのように解決しますか?

推奨学習: Redis 学習チュートリアル

キャッシュとデータベースの間でデータの不一致はどのようにして発生しますか?

まず、「データの整合性」とは具体的に何を意味するのかを理解する必要があります。実際、ここでの「一貫性」には 2 つの状況が含まれます:

  • キャッシュ内にデータがある場合、キャッシュされたデータの値はデータベース内の値と同じである必要があります。 #キャッシュ内にはデータそのものが存在しないため、データベース内の値が最新の値である必要があります。
  • これら 2 つの状況が満たされない場合、キャッシュとデータベース間のデータの不整合の問題が発生します。ただし、キャッシュの読み取りモードと書き込みモードが異なると、キャッシュデータの不整合の発生が異なり、対応方法も異なりますので、まず、キャッシュの読み取りモードと書き込みモードに応じて、異なるモードでのキャッシュの不整合を理解します。状態。キャッシュは読み取り/書き込みキャッシュと読み取り専用キャッシュに分けることができます。

読み取り/書き込みキャッシュの場合、データを追加、削除、または変更する場合は、キャッシュ内で行う必要があります。同時に、同期ベースでデータをデータベースに書き戻すかどうかを決定する必要があります。採用されたライトバック戦略について。

同期直接書き込み戦略: キャッシュを書き込むとき、データベースも同期的に書き込まれ、キャッシュ内のデータとデータベースの一貫性が保たれます。

非同期ライトバック戦略:キャッシュにデータが書き込まれるまで、データベースは同期的に書き込まれません。キャッシュからデータが削除されると、データはデータベースに書き戻されます。この戦略を使用する場合、データがデータベースに書き戻されていない場合、キャッシュは失敗し、この時点ではデータベースには最新のデータがありません。

したがって、読み取り/書き込みキャッシュの場合、キャッシュ内のデータとデータベースの一貫性を確保したい場合は、同期直接書き込み戦略を採用する必要があります。ただし、この戦略を採用する場合は、キャッシュとデータベースを同時に更新する必要があることに注意してください。したがって、ビジネス アプリケーションでトランザクション メカニズムを使用して、キャッシュとデータベースの更新がアトミックであることを保証する必要があります。つまり、両方が同時に更新されるか、どちらも更新されず、エラー メッセージが返され、再試行が実行されます。そうしないと、同期直接書き込みを実現できません。

もちろん、シナリオによっては、データの一貫性に対する要件がそれほど高くない場合もあります。たとえば、電子商取引商品の重要ではない属性や、短いビデオの作成時間や変更時間をキャッシュする場合、非同期ライトバック戦略を使用できます。

読み取り専用キャッシュについて話しましょう。読み取り専用キャッシュの場合、新しいデータがある場合はデータベースに直接書き込まれます。データが削除された場合は、読み取り専用キャッシュ内のデータを無効としてマークする必要があります。このように、アプリケーションがその後、これらの追加、削除、または変更されたデータにアクセスすると、キャッシュ内に対応するデータがないため、キャッシュ ミスが発生します。このとき、アプリケーションはデータベースからデータをキャッシュに読み取ります。これにより、後でデータにアクセスするときに、キャッシュから直接データを読み取ることができます。

次に、次の図に示すように、Tomcat による MySQL へのデータの書き込みと削除を例として、データの追加、削除、および変更操作がどのように実行されるかを説明します。図からわかるように、Tomcat 上で実行されているアプリケーションは、データ X の追加 (Insert 操作)、変更 (Update 操作)、または削除 (Delete 操作) のいずれであっても、データベース内のデータを直接追加、変更、および削除します。もちろん、アプリケーションが変更または削除操作を実行すると、キャッシュされたデータ X も削除されます。

では、このプロセスでデータの不整合は発生するのでしょうか?データの追加と削除では状況が異なるため、分けて見ていきます。

新しいデータ

新しいデータの場合、データはキャッシュに対する操作を行わずにデータベースに直接書き込まれます。この時点では、キャッシュ自体には新しいデータはありません。この状況は、先ほど述べた整合性の 2 番目の状況と一致するため、この時点ではキャッシュとデータベースのデータは整合しています。

    データの削除
  1. 削除操作が発生した場合、アプリケーションはデータベースを更新し、キャッシュ内のデータを削除する必要があります。これら 2 つの操作が原子性を保証できない場合、つまり両方が完了するか、どちらも完了しない場合、データの不整合が発生します。この問題はさらに複雑なので、分析してみましょう。
  2. アプリケーションが最初にキャッシュを削除し、次にデータベースを更新すると仮定します。キャッシュは正常に削除され、データベースの更新に失敗した場合、アプリケーションが再度データにアクセスすると、データは存在しません。キャッシュ内に存在すると、キャッシュミスが発生します。その後、アプリケーションは再びデータベースにアクセスしますが、データベース内の値は古い値であり、アプリケーションは古い値にアクセスします。
    例を示します。まず下の図を見てください。


アプリケーションは、データ X の値を 10 から 3 に更新したいと考えています。まず、Redis キャッシュ内の X のキャッシュ値を削除しますが、データベースの更新は失敗します。他に同時アクセス要求がある場合
最初にデータベースを更新してからキャッシュ内の値を削除すれば、この問題は解決できるのかと疑問に思われるかもしれません。もう一度分析してみましょう。
アプリケーションが最初にデータベースの更新を完了したが、キャッシュの削除に失敗した場合、データベース内の値は新しい値であり、キャッシュ内の値は古い値であり、これは明らかに矛盾しています。このとき、データにアクセスする他の同時リクエストがある場合、通常のキャッシュ アクセス プロセスに従って、最初にキャッシュがクエリされますが、この時点では古い値が読み取られます。
例を使って説明しましょう。

Redis はキャッシュの不整合の問題をどのように解決しますか?

アプリケーションはデータ X の値を 10 から 3 に更新したいと考えています。最初にデータベースが正常に更新され、次に Redis キャッシュ内の X のキャッシュが削除されますが、この操作は失敗しました。この時点で、データベース内の X の新しい値は 3 ですが、Redis にキャッシュされた X の値は 10 であり、これは明らかに矛盾しています。この時点で別のクライアントがたまたま X にアクセスするリクエストを送信した場合、最初に Redis でクエリを実行し、クライアントはキャッシュ ヒットを見つけますが、古い値 10 が読み取られます。

わかりました。ここでは、データベースの更新とキャッシュされた値の削除のプロセスで、2 つの操作のどちらが先に実行されるか後で実行されるかに関係なく、一方の操作が失敗する限り、クライアントに問題が発生することがわかります。古い価値観を読むためです。先ほど述べた 2 つの状況を要約して、以下の表を作成しました。

Redis はキャッシュの不整合の問題をどのように解決しますか?

問題の原因はわかっていますが、どうすれば解決できますか?

データの不整合の問題を解決するにはどうすればよいですか?

まず最初に、再試行メカニズムというメソッドを紹介します。

具体的には、削除するキャッシュ値または更新するデータベース値をメッセージ キューに一時的に保存できます (たとえば、Kafka メッセージ キューを使用)。アプリケーションがキャッシュされた値の削除またはデータベース値の更新に失敗した場合、メッセージ キューから値を再度読み取り、再度削除または更新することができます。

削除または更新が成功した場合は、操作の繰り返しを避けるために、これらの値をメッセージ キューから削除します。このとき、データベースとキャッシュされたデータの一貫性も確保できます。それ以外の場合は、もう一度試す必要があります。一定の回数を超えても再試行が失敗する場合は、ビジネス層にエラー メッセージを送信する必要があります。

次の図は、データベースを更新してからキャッシュ値を削除する場合で、キャッシュの削除に失敗した場合は、リトライして削除が成功する様子を確認できます。

Redis はキャッシュの不整合の問題をどのように解決しますか?

私が今話したのは、データベースの更新とキャッシュされた値の削除のプロセス中に操作の 1 つが失敗する状況です。実際、これら 2 つの操作が失敗したとしても、初めて実行されました どれも失敗しませんでした 多数の同時リクエストがある場合、アプリケーションは一貫性のないデータを読み取る可能性があります。

同様に、削除順序と更新順序の違いに応じて 2 つの状況に分けます。どちらの場合でも、ソリューションも異なります。

シナリオ 1: まずキャッシュを削除してから、データベースを更新します。

スレッド A がキャッシュ値を削除した後、データベースを更新する前にスレッド B がデータの読み取りを開始するとします (たとえば、ネットワークの遅延がある)。スレッド B はキャッシュが見つからないことがわかり、データベースからの読み取りのみが可能になります。これにより 2 つの問題が発生します:

  1. スレッド B は古い値を読み取ります。
  2. スレッド B はキャッシュが見つからないときにデータベースを読み取るため、古い値をデータベースにも書き込みます。これにより、他のスレッドがキャッシュから古い値を読み取る可能性があります。

スレッド B がデータベースからデータを読み取ってキャッシュを更新するまで待ち、その後スレッド A がデータベースの更新を開始します。この時点で、キャッシュ内のデータは古い値ですが、データはデータベース内の は最新の値です。この 2 つは矛盾しています。

この状況を表にまとめてみました。 ############私たちは何をすべきか?解決策をご紹介します。
Redis はキャッシュの不整合の問題をどのように解決しますか?

スレッド A がデータベース値を更新した後、スレッド A を短期間スリープさせてから、キャッシュ削除操作を実行できます。

スリープ期間を追加する理由は、スレッド B が最初にデータベースからデータを読み取り、次に欠落したデータをキャッシュに書き込んでから、スレッド A がそのデータを削除できるようにするためです。したがって、スレッド A がスリープする時間は、スレッド B がデータを読み取ってキャッシュに書き込む時間よりも長くする必要があります。今回はどうやって決めるのでしょうか?業務プログラム実行時にデータの読み込みやキャッシュの書き込みを行うスレッドの動作時間を計測し、見積もることをお勧めします。

このようにして、他のスレッドがデータを読み取るときに、キャッシュが欠落していることがわかり、データベースから最新の値を読み取ります。このソリューションでは、キャッシュされた値を初めて削除した後、一定期間削除が遅れるため、「遅延二重削除」とも呼ばれます。

次の疑似コードは、「遅延二重削除」スキームの例です。ご覧ください。

redis.delKey(X)
db.update(X)
Thread.sleep(N)
redis.delKey(X)
ログイン後にコピー

シナリオ 2: 最初にデータベース値を更新し、次にキャッシュ値を削除します。

スレッド A がデータベース内の値を削除したが、キャッシュ値を削除する前に、スレッド B がデータの読み取りを開始した場合、スレッド B がキャッシュにクエリを実行すると、キャッシュ ヒットが見つかりました。古い値がキャッシュから直接読み取られます。ただし、この場合、他のスレッドからキャッシュを読み取る同時リクエストがそれほど多くなければ、古い値を読み取るリクエストも多くありません。また、スレッド A は通常、キャッシュされた値をすぐに削除するため、別のスレッドが再度読み取るとキャッシュ ミスが発生し、最新の値がデータベースから読み取られます。したがって、この状況がビジネスに与える影響はほとんどありません。

最初にデータベースを更新してからキャッシュされた値を削除する状況を示すために、別の表を描画します。
Redis はキャッシュの不整合の問題をどのように解決しますか?

さて、キャッシュとデータベース間のデータの不整合は、一般に 2 つの理由によって引き起こされることがわかりました。対応する解決策を提供しました。

  • キャッシュされた値の削除またはデータベースの更新に失敗すると、データの不整合が発生します。再試行メカニズムを使用して、削除または更新操作が成功したことを確認できます。
  • キャッシュされた値の削除とデータベースの更新の 2 つの手順では、他のスレッドからの読み取り操作が同時に行われ、他のスレッドが古い値を読み取ることになります。解決策は、二重削除を遅らせることです。

推奨される学習: Redis ビデオ チュートリアル

以上がRedis はキャッシュの不整合の問題をどのように解決しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:csdn.net
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート