1. Redis にデータがある場合、データベース内の値と同じである必要があります。
2. Redis にデータがない場合は、データベース内の最新の値で Redis を同期して更新する必要があります。
データベースへの書き込みは、Redis キャッシュにも同期的に書き込みます。キャッシュは、次のデータと一貫性があります。データベース; 読み取り/書き込みキャッシュ用 つまり、キャッシュとデータベース内のデータの一貫性を確保するには、同期直接書き込み戦略を確保する必要があります。
一部の業務運営では、物流システムなど、MySQL データが更新された後、一定期間後に Redis データを同期することが許可されています。
異常な状況が発生した場合、失敗したアクションに再パッチを適用する必要があり、rabbitmq または kafka を使用して書き直す必要があります。
複数のスレッドがデータベース内のこのデータを同時にクエリする場合、最初のリクエストでミューテックス ロックを使用してデータをクエリできます。 。
他のスレッドは、このステップでロックを取得できなくなるまで待機し、最初のスレッドがデータをクエリするのを待ってから、データをキャッシュします。
後続のスレッドが入ってきて、すでにキャッシュがあることがわかるため、キャッシュに直接アクセスします。
public String get(String key){ // 从Redis缓存中读取 String value = redisTemplate.get(key); if(value != null){ return value; } synchronized (RedisTest.class){ // 重新尝试从Redis缓存中读取 value = redisTemplate.get(key); if(value != null){ return value; } // 从MySQL数据库中查询 value = studentDao.get(key); // 写入Redis缓存 redisTemplate.setnx(key,value,time); return value; } }
常識に従えば、次のようになります。右?それで、この場合何が問題なのでしょうか?
データベースが正常に更新された後、Redis を更新する前に例外が発生した場合はどうなりますか?
データベースは Redis のキャッシュされたデータと矛盾しています。
マルチスレッドの状況では問題が発生します。
例:
スレッド 1 は redis = 200 を更新します;
スレッド 2 は redis = 100 を更新します;
スレッド 2 は MySQL = 100 を更新します;
スレッド 1 は MySQL = 200 を更新します;
結果は次のようになります。 Redis= 100, MySQL=200; 消去します!
スレッド 1 は Redis キャッシュ データを削除し、次に MySQL データベースを更新しました。
MySQL の更新が完了する前に、スレッド 2 は、 kill 、キャッシュされたデータの読み取りに来ました;
ただし、この時点では MySQL データベースは更新されていないため、スレッド 2 は MySQL の古い値を読み取り、その後、スレッド 2 も古い値をデータ キャッシュとして Redis に書き込みます。 ;
スレッド1MySQLのデータを更新したところ、Redisに以前削除したデータが存在することが判明したので更新しません;
以上です。 。
遅延二重削除は、スリープ時間がスレッド 2 がデータを読み取ってからキャッシュに書き込む時間より長い限り、つまり、上記の問題を解決できます。 、スレッド 1 Redis キャッシュ内のデータが最新であることを確認するために、スレッド 2 がキャッシュに書き込んだ後に 2 番目のキャッシュ クリア操作を実行する必要があります。
/** * 延时双删 * @autor 哪吒编程 */ public void deleteRedisData(Student stu){ // 删除Redis中的缓存数据 jedis.del(stu); // 更新MySQL数据库数据 studentDao.update(stu); // 休息两秒 try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } // 删除Redis中的缓存数据 jedis.del(stu); }
遅延二重削除の最大の問題はスリープです。効率が重視される今日では、スリープを使用しない方が賢明です。
寝なくても遅いと思いますが、それでも寝てしまいます...
スレッド 1 は最初にデータベースを更新し、次に Redis キャッシュを削除します。
スレッド 2 は、スレッド 1 が Redis キャッシュを削除する前にリクエストを開始し、削除されていない Redis を取得します。キャッシュ;
現時点では、スレッド 1 は Redis キャッシュ データのみを削除します;
問題はまだ存在しており、無限に行ったり来たりしています。 。
この状況を解決するにはどうすればよいですか?
バトルを解決するためのメッセージミドルウェアを導入し、改めて詳しく見直します。
方法③の睡眠は常に頭痛の種です;
方法④はより包括的な解決策ですが、学習コストが増加しますメッセージミドルウェアの追加による保守コストも発生します。
5. MySQL マスター/スレーブ レプリケーションの動作原理
1. マスター サーバー上のデータが変更されると、その変更はバイナリ イベントに書き込まれます。ログ ファイル内;
2. スレーブ スレーブ サーバーは、一定の時間間隔内でマスター サーバー上のバイナリ ログを検出し、変更があったかどうかを検出します。サーバーのバイナリ イベント ログが変更されると、I/O スレッドが開始されてマスター バイナリ イベント ログ (3) を要求します。同時にマスター サーバーは、各 I/O スレッドのダンプ スレッドを開始して、バイナリ イベント ログを送信します;4. スレーブは、サーバーから受信したバイナリ イベント ログを独自のローカル リレー ログ ファイルに保存します;5. スレーブ スレーブ サーバーは SQL スレッドを開始してリレー ログからバイナリ ログを読み取り、ローカルで再生してデータをメイン サーバーと一貫性を保ちます;
6. 最終 I/Oスレッドと SQL スレッドはスリープ状態になり、次に目覚めるまで待機します。
以上がMySQL データベースと Redis キャッシュの一貫性のための更新戦略は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。