MySQL データベースと Redis キャッシュの一貫性のための更新戦略は何ですか?

WBOY
リリース: 2023-05-27 15:11:24
転載
738 人が閲覧しました

    1. 更新戦略

    1. Redis にデータがある場合、データベース内の値と同じである必要があります。

    2. Redis にデータがない場合は、データベース内の最新の値で Redis を同期して更新する必要があります。

    2. 読み取り/書き込みキャッシュ

    1. 同期直接書き込み戦略

    データベースへの書き込みは、Redis キャッシュにも同期的に書き込みます。キャッシュは、次のデータと一貫性があります。データベース; 読み取り/書き込みキャッシュ用 つまり、キャッシュとデータベース内のデータの一貫性を確保するには、同期直接書き込み戦略を確保する必要があります。

    2. 非同期書き込み遅延戦略

    一部の業務運営では、物流システムなど、MySQL データが更新された後、一定期間後に Redis データを同期することが許可されています。

    異常な状況が発生した場合、失敗したアクションに再パッチを適用する必要があり、rabbitmq または kafka を使用して書き直す必要があります。

    3. ロック戦略を再確認する

    複数のスレッドがデータベース内のこのデータを同時にクエリする場合、最初のリクエストでミューテックス ロックを使用してデータをクエリできます。 。

    他のスレッドは、このステップでロックを取得できなくなるまで待機し、最初のスレッドがデータをクエリするのを待ってから、データをキャッシュします。

    後続のスレッドが入ってきて、すでにキャッシュがあることがわかるため、キャッシュに直接アクセスします。

    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;
        }
    }
    ログイン後にコピー

    4. データベースとキャッシュの一貫性のための更新戦略

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

    常識に従えば、次のようになります。右?それで、この場合何が問題なのでしょうか?

    データベースが正常に更新された後、Redis を更新する前に例外が発生した場合はどうなりますか?

    データベースは Redis のキャッシュされたデータと矛盾しています。

    2. 最初にキャッシュを更新し、次にデータベースを更新します

    マルチスレッドの状況では問題が発生します。

    例:

    • スレッド 1 は redis = 200 を更新します;

    • スレッド 2 は redis = 100 を更新します;

    • スレッド 2 は MySQL = 100 を更新します;

    • スレッド 1 は MySQL = 200 を更新します;

    結果は次のようになります。 Redis= 100, MySQL=200; 消去します!

    3. まずキャッシュを削除し、次にデータベースを更新します。

    スレッド 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);
    }
    ログイン後にコピー

    遅延二重削除の最大の問題はスリープです。効率が重視される今日では、スリープを使用しない方が賢明です。

    寝なくても遅いと思いますが、それでも寝てしまいます...

    4. まずデータベースを更新してから、キャッシュを削除してください

    1. スレッド 1 は最初にデータベースを更新し、次に Redis キャッシュを削除します。

    2. スレッド 2 は、スレッド 1 が Redis キャッシュを削除する前にリクエストを開始し、削除されていない Redis を取得します。キャッシュ;

    3. 現時点では、スレッド 1 は Redis キャッシュ データのみを削除します;

    問題はまだ存在しており、無限に行ったり来たりしています。 。

    この状況を解決するにはどうすればよいですか?

    バトルを解決するためのメッセージミドルウェアを導入し、改めて詳しく見直します。

    1. #データベースを更新します;

    2. #データベースは操作情報を binlog ログに書き込みます;
    3. # #プログラムをサブスクライブします キーとデータを抽出します;
    4. キャッシュ操作を削除してみて、削除が失敗したことがわかります;
    5. これらのデータ情報を送信しますメッセージミドルウェアへ;
    6. メッセージミドルウェアからデータを取得して再操作;
    7. 5. 概要
    Nezha は、最初にデータベースを更新してからキャッシュを削除する 4 つの方法を使用することをお勧めします。

    方法①と方法②の欠点はあまりに明白なので検討することはできません;

    方法③の睡眠は常に頭痛の種です;

    方法④はより包括的な解決策ですが、学習コストが増加しますメッセージミドルウェアの追加による保守コストも発生します。


    5. MySQL マスター/スレーブ レプリケーションの動作原理

    1. マスター サーバー上のデータが変更されると、その変更はバイナリ イベントに書き込まれます。ログ ファイル内; MySQL データベースと Redis キャッシュの一貫性のための更新戦略は何ですか?

    2. スレーブ スレーブ サーバーは、一定の時間間隔内でマスター サーバー上のバイナリ ログを検出し、変更があったかどうかを検出します。サーバーのバイナリ イベント ログが変更されると、I/O スレッドが開始されてマスター バイナリ イベント ログ (

    3) を要求します。同時にマスター サーバーは、各 I/O スレッドのダンプ スレッドを開始して、バイナリ イベント ログを送信します;

    4. スレーブは、サーバーから受信したバイナリ イベント ログを独自のローカル リレー ログ ファイルに保存します;

    5. スレーブ スレーブ サーバーは SQL スレッドを開始してリレー ログからバイナリ ログを読み取り、ローカルで再生してデータをメイン サーバーと一貫性を保ちます;

    6. 最終 I/Oスレッドと SQL スレッドはスリープ状態になり、次に目覚めるまで待機します。

    以上がMySQL データベースと Redis キャッシュの一貫性のための更新戦略は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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