Redisデータ整合性スキームの分析と研究

以下をクリックしてフォローし、右上隅の「スターに設定」をクリックして、できるだけ早く更新情報を受け取ります~~~

一般的なビジネス シナリオでは、読み取りが増加し、書き込みが減少します。クライアントのリクエストが多すぎると、データベースへの負荷が増大します。データベースへの負荷を軽減するためにキャッシュを導入することは避けられない選択です。現在、業界の主流の選択は次のとおりです。 Redis をデータベース キャッシュとして使用します。しかし、キャッシュの導入後、システム設計に大きな課題が生じ、その中でもキャッシュとデータベース間のデータ整合性の問題は非常に難しい問題でした。今日は、このプロジェクトでどのようなソリューションを使用したかについて説明します。データの一貫性の問題を解決します。

1

Redis の使用シナリオ

bbceb65e690e776cda4de5b52d6d0f31.png

実際のプロジェクトでは、アプリケーションは通常、読み取りが多くなり、書き込みは少なくなります。通常、データベース読み取りのプレッシャーの問題を解決するために Redis を使用します。言い換えれば、クライアントの頻繁なクエリによって引き起こされるデータベースへの影響を軽減するために、Redis をキャッシュとして使用します。データベースの圧力。

したがって、プロジェクトでは、クライアントが Redis キャッシュにクエリを実行するのではなく、クライアントがデータベースに直接クエリを実行してデータを返します。キャッシュにデータがある場合は、データが直接返されます。キャッシュにデータがない場合は、データベースがクエリされ、同時にデータベース データが Redis キャッシュに書き込まれます。

e455a1d6f394b4ca67416239a94db6dc.png

上記の使用シナリオでは、通常、電子商取引プラットフォームでの売れ筋商品、ユーザーのログイン情報、ニュース プラットフォームでの注目のニュースなどの注目のデータがキャッシュされます。

2

データの一貫性の問題の原因

be3866656da2c9c3d728e190c26f3f5e.png

Redisキャッシュを導入するとデータベース内のデータが変更されるとデータ操作の難易度が上がりますデータベースとRedisの両方を操作する必要がありますRedisとデータベースの操作には以下の2つのオプションがあります。

1. Redisを操作してからデータベースを操作する

2. 最初にデータベースを操作し、次に Redis を操作します。

上記のオプションのどれを選択しても、データ操作が成功するか失敗することを誰もが望んでいますが、データの不整合が生じるため、失敗と成功の結果は見たくありません。

例を挙げる:

Redis に注目の商品データがキャッシュされているとします。キー 1001 の商品があり、名前は「Huawei 携帯電話」です。データベース内の商品名 1001 番も Huawei 携帯電話です。このとき、販売者は次のように感じます。製品名が Huawei 携帯電話であるということは、少し広義なので正確にする必要があるため、製品番号 1001 の名前を、対応する具体的な名前「Huawei P40 Pro」に変更します。

1. 最初に Redis を操作してからデータベースを操作することを選択した場合、Redis 操作が成功し、データベース操作が失敗すると、Redis 内の名前は「Huawei P40 Pro」に変更されますが、データベースの名前は「Huawei」のままです。携帯電話」により、データの不整合の問題が発生します。

2. 最初にデータベースを操作してから Redis を操作することを選択した場合、データベースの操作が成功し、Redis の操作が失敗すると、データベース内の名前は「Huawei P40 Pro」に変更されますが、Redis の名前は「Huawei」のままです。携帯電話」により、データの不整合の問題が発生します。

Redis とデータベースは 2 つの異なるミドルウェアであるため、トランザクションを通じてデータの一貫性の問題をうまく解決することはできず、リアルタイムのデータの一貫性とシステムのパフォーマンスの間でトレードオフを判断し、許容可能なソリューションを選択するしかありません。

データベースは安定した永続的なシステムであり、Redis よりも信頼性が高いため、通常はデータベース データを標準として使用します。このデータの一貫性の問題を解決する原則は、Redis キャッシュ データの有効期限を設定できるということです。データの有効期限が切れたら、データベースにアクセスしてクエリを実行し、データの整合性を確保するためにデータベース データを Redis キャッシュに書き込みます。

この有効期限の範囲内でデータの更新操作が発生し、一方の更新操作が失敗し、もう一方の更新操作が成功すると、不整合の問題が発生します。有効期限の設定が短すぎるため、データベースへの負荷が依然として非常に高くなります。有効期限時間設定が長すぎると不整合の問題が顕著になるため、データベースのデータを基準とする原則に基づいてデータの整合性問題の解決策を引き続き検討する必要があります。

3

データ更新時のRedisの操作方法

60417e1c8e4db6dba7bd27a45f422138.png

データを更新する場合、データベースの操作には慣れており、データベースの値を直接更新するだけですが、Redis を操作する場合はどうすればよいでしょうか。

1. これは単純ではないという人もいるでしょうが、データが変更されると、キャッシュが直接更新されます。

2. データが変更されるとキャッシュされたデータが削除されるという人もいますが、クエリ リクエストでキャッシュにデータがないことが判明すると、データベースから新しいデータがロードされます。

上記のどちらの方法も考えられますが、どのように選択すればよいのでしょうか。

Redis を更新することを選択した場合、更新のコストが高いかどうかを評価する必要があります。たとえば、Redis に更新するデータを取得するには、多くのテーブルでの関連クエリ、または複数のインターフェイスでのクエリ呼び出し、および取得するための多くの計算が必要です。このような複雑な更新プロセスに直面している場合は、データを直接削除することをお勧めします。更新するデータを直接取得できる場合は、Redis を更新することを選択することが可能です。

Redis キャッシュ データを直接削除する方が簡単です。キャッシュ データが削除された後は、データベースからのみ読み取ることができるため、不整合を回避できます。インターネット企業は通常、Redis を削除するソリューションを選択します。

以下では、オプションのソリューションを表す図を使用します。

33dad3e37ef2cb586358a196ac9e2f35.png

上図より、データ変更時のRedisとデータベースの処理の流れを、Redisの更新と削除の2つの側面から分析し、次にRedisを先に操作するかデータベースを先に操作するかの2つの側面から分析できることがわかります。この考え方に沿って詳細な分析を続けてみましょう。

4

Redis 更新プランを選択します

c22ccceea50c3deec728e9147925e2f7.png

1. 最初に Redis を更新し、次にデータベースを更新します

まず第一に、このオプションを選択することはお勧めできません。

データの一貫性の基本原則はデータベース内のデータに基づいているため、最初にキャッシュを更新すると、キャッシュの更新は成功してもデータベースの更新が失敗する状況が発生します。このとき、私たちが直面している問題にはローリングが必要です。先ほど成功したキャッシュ更新を元に戻す操作を実行するには、この例外を処理するために多くの判断ロジックをビジネス コードに追加する必要があります。データの変更が挿入、更新、削除などであるかどうかを考慮し、別の処理を実行する必要があります。さまざまなシナリオに応じてロールバックを計画します。この種のロールバック操作はより面倒です。ビジネス コードへの侵入も比較的大きいため、このオプションはお勧めできません。

もちろん、ビジネスレベルでこの種のデータの不整合が許容される場合は、異常事態を考慮する必要はなく、このオプションも許容されます。

2. 最初にデータベースを更新し、次に Redis を更新します

最初にデータベースを更新してから Redis を更新するソリューションでは、データベース操作が最初に行われます。データベース操作が失敗した場合、クライアントはデータベース操作を再度開始するだけで済みます。

データベース操作は成功したが、Redis 操作が失敗した場合、データベース データは正常に設定されているため、Redis データを正常に操作する方法について説明することに重点を置きます。クライアントレベルで見ると、彼が提出したデータはすでにシステム内に存在しており、現時点での問題は、それをシステム内でどのように解決するかです。

Redis 操作の失敗については、ビジネスで必要なデータ整合性レベルに応じて比較検討して選択できる次のオプションがあります。

1. 何も操作せず、Redis にキャッシュされたデータの有効期限が切れるのを待ち、データベースから最新のデータを自動的に同期します。この時点で、最も深刻なデータの不整合期間はキャッシュの有効期限期間です (この期間を考慮してください)。有効期限) ; この期間内に新しい更新リクエストがあった場合、今回はキャッシュの更新が成功する可能性があります。

2. データの一貫性要件が比較的高い場合は、Redis 操作が失敗した後、操作を記録し、非同期で処理し、Redis データを使用してデータベースと比較します。一貫性がない場合は、キャッシュを再度更新して、キャッシュされたデータはデータベース データと一致します。

5

Redis の削除計画を選択します

32e69376e2e67251301a76591863cec7.png

現在のデータ変更により、主流のソリューションは Redis を削除することであるため、このソリューションの分析に重点を置きます。

1. まずデータベースを更新してから、Redis を削除します

データベースの更新は成功したが、Redis の削除に失敗した場合、古い値が Redis に保存され、キャッシュの削除に失敗すると、キャッシュ内のデータとデータベースの不整合が発生します。

Redis の削除に失敗するという異常な状況を分析するには、通常、次の解決策があります。

1. 削除を再試行できます。たとえば、削除アクションをメッセージ キュー MQ に送信すると、MQ コンシューマーはキーを削除し、キャッシュの削除が成功することを確認するために一斉に削除操作を試行します。解決策はキャッシュを削除することです。コード実装によるビジネス ロジックへの侵入があります。

2. もう 1 つのソリューションは、ビジネス ロジックに侵入せず、バイナリログの変更を監視することによってキャッシュを削除する完全な非同期ソリューションです。データベースを更新すると、ビンログが生成されます。データベースのビンログの変更を監視し、キャッシュを非同期に削除するサービスを使用できます。アリババのオープンソースの運河は、ビンログを監視できるツールです。データが変更される限り、 Redis データは削除できます。

2. まず Redis を削除してからデータベースを更新します

Redis キャッシュの削除には成功したが、データベースの更新に失敗した場合は、データベースに基づいているため、もう一度確認するだけで済みます。この解決策は理想的であり、問​​題はありません。実際、同時実行下ではデータの一貫性の問題も発生する可能性があります。 。

まず、同時環境での更新とクエリのプロセスを見てみましょう。

7027b359d045caa00ec07b8a0831836b.png

上図は、Thread-1 が更新処理、Thread-2 がクエリ処理であり、CPU の実行順序は、 Thread-1 がキャッシュの削除に成功し、この時点で Thread-2 が CPU がクエリを実行したことを取得することを示しています。キャッシュにデータがない場合、データベースにクエリを実行してデータベースを配置します。スレッド 1 がデータベースを更新するためにまだ実行されていないため、値がキャッシュに書き込まれます。そのため、キャッシュ内の値は古い値 (古い値) になります。最後に、CPU はスレッド 1 のコードを実行してデータベースを正常に更新するため、この時点のデータベースの値は 新規 (新規) を追加すると、データ行の不整合の問題が発生します。

上記の問題を解決するには、通常、次のオプションがあります。

1. 同時マルチスレッド操作では、次のスレッドが実行される前に、同じ操作の 2 つのステップを同時に完了できますか? 各スレッドを操作のキューに入れます。ロックするという人もいます。サービスが複数にデプロイされている場合分散ロックになるか、分散キューがデータベースまたは Redis を順番に操作します。副作用として、データベースは元々は同時実行でしたが、現在はシリアルになっているため、この解決策は実現可能ではないようです。ロックまたはキューイング実行スキームによりシステムのパフォーマンスが低下します。

2. もう 1 つの解決策は、二重削除を遅らせることです。つまり、最初にキャッシュを削除し、次にデータベースを更新し、データの更新後に一定期間スリープしてから、再度キャッシュを削除します。

疑似コードは次のとおりです。

redes.del(key);
db.update(data);
Thread.sleep(2000);
redes.del(key);

上記のソリューションはすべてソリューションです。どのソリューションが優れているか、どのソリューションが実現不可能であるということはありません。上記のソリューションはすべて、リアルタイムの一貫性とシステム パフォーマンスに基づいています。異なるビジネスに応じて、異なるデータは一貫しています。パフォーマンス要件、システムのパフォーマンスと組み合わせて、総合的に考慮して、システムに合ったソリューションを選択してください。

一般に、私たちの基本原則はデータベースを標準とすることであるため、選択するソリューションはデータベースの操作を最初に置く必要があります、つまり、最初にデータベースを操作し、次に Redis を操作する必要があります。メッセージ キューを使用すると、データベースを操作する前にデータベースに対するクライアント リクエストの負荷を軽減できます。

おすすめ

転載: blog.csdn.net/z123456789XDW/article/details/132820119