ホームページ  >  記事  >  Java  >  Java に基づいて Redis マルチレベル キャッシュを実装する方法

Java に基づいて Redis マルチレベル キャッシュを実装する方法

WBOY
WBOY転載
2023-05-13 19:52:17968ブラウズ

1. マルチレベル キャッシュ

1. 従来のキャッシュ ソリューション

リクエストが Tomcat に到達すると、まず Redis にアクセスしてキャッシュを取得します。

Java に基づいて Redis マルチレベル キャッシュを実装する方法

#2. マルチレベル キャッシュ ソリューション

  • # Tomcat の同時リクエストの数 は Redis よりもはるかに小さいため、Tomcat がボトルネックになります

  • リクエスト処理の各リンクを使用してキャッシュをそれぞれ追加し、Tomcat への負荷を軽減し、サービスのパフォーマンスを向上させます

Java に基づいて Redis マルチレベル キャッシュを実装する方法# #2. JVM ローカル キャッシュ

キャッシュはメモリに保存されるため、データの読み取り速度が速くなり、データの読み込み速度が大幅に向上します。データベースへのアクセスを軽減し、データベースへの負荷を軽減します。

redis などの分散キャッシュ
- 利点: 大容量のストレージ、信頼性が高く、クラスター内で共有できます

-欠点: キャッシュへのアクセスにネットワーク オーバーヘッドが発生します
- シナリオ: 大量のキャッシュ データ、高信頼性、クラスター内に存在する必要がある共有データ

ローカル キャッシュを処理し、 HashMap、GuavaCache など
- 長所: ローカル メモリの読み取り、ネットワーク オーバーヘッドなし、高速

- 短所: ストレージ容量が限られ、信頼性が低い (再起動後に失われるなど)、クラスター内で共有できない
-シナリオ: 高パフォーマンス要件、少量のキャッシュ データ

1. 実際のケース

    Caffeine は、Java8 に基づいて開発された高性能ローカル キャッシュ ライブラリです。
  • #これは現在 Spring の内部キャッシュに使用されています
  • ##
    <dependency>
         <groupId>com.github.ben-manes.caffeine</groupId>
         <artifactId>caffeine</artifactId>
         <version>3.0.5</version>
     </dependency>
    package com.erick.cache;
    
    import com.github.benmanes.caffeine.cache.Cache;
    import com.github.benmanes.caffeine.cache.Caffeine;
    
    import java.time.Duration;
    
    public final class CacheUtil {
        private static int expireSeconds = 2;
        public static Cache<String, String> cacheWithExpireSeconds;
    
        private static int maxPairs = 1;
        public static Cache<String, String> cacheWithMaxPairs;
    
        static {
            /*过期策略,写完60s后过期*/
            cacheWithExpireSeconds = Caffeine.newBuilder()
                    .expireAfterWrite(Duration.ofSeconds(expireSeconds))
                    .build();
    
            /*过期策略,达到最大值后删除
             * 1. 并不会立即删除,等一会儿才会删除
             * 2. 会将之前存储的数据删除掉*/
            cacheWithMaxPairs = Caffeine.newBuilder()
                    .maximumSize(maxPairs)
                    .build();
        }
    
        /*从缓存中获取数据
         * 1. 如果缓存中有,则直接从缓存中返回
         * 2. 如果缓存中没有,则去数据查询并返回结果*/
        public static String getKeyWithExpire(String key) {
            return cacheWithExpireSeconds.get(key, value -> {
                return getResultFromDB();
            });
        }
    
        public static String getKeyWithMaxPair(String key) {
            return cacheWithMaxPairs.get(key, value -> {
                return getResultFromDB();
            });
        }
    
        private static String getResultFromDB() {
            System.out.println("数据库查询");
            return "db result";
        }
    }
    package com.erick.cache;
    
    import java.util.concurrent.TimeUnit;
    
    public class Test {
    
        @org.junit.Test
        public void test01() throws InterruptedException {
            CacheUtil.cacheWithExpireSeconds.put("name", "erick");
            System.out.println(CacheUtil.getKeyWithExpire("name"));
            TimeUnit.SECONDS.sleep(3);
            System.out.println(CacheUtil.getKeyWithExpire("name"));
        }
    
        @org.junit.Test
        public void test02() throws InterruptedException {
            CacheUtil.cacheWithMaxPairs.put("name", "erick");
            CacheUtil.cacheWithMaxPairs.put("age", "12");
    
            System.out.println(CacheUtil.getKeyWithMaxPair("name"));
            System.out.println(CacheUtil.getKeyWithMaxPair("age"));
    
            TimeUnit.SECONDS.sleep(2);
    
            System.out.println(CacheUtil.getKeyWithMaxPair("name")); // 查询不到了
            System.out.println(CacheUtil.getKeyWithMaxPair("age"));
        }
    }

    3. キャッシュの一貫性

  • 1. 一般的な解決策

1.1 キャッシュに有効期間を設定する

有効期間を設定し、有効期限が切れたら自動的に削除します。再クエリ時に更新可能
  • 利点: シンプルで便利

  • 欠点: 適時性が低く、キャッシュの有効期限が切れる前にキャッシュが不整合になる可能性があります

  • シナリオ: 更新頻度が低く、適時性要件が低いビジネス

  • 1.2 同期二重書き込み

データベースを変更する場合、同時にキャッシュを直接変更します。
  • 利点: コードの侵入、キャッシュとデータベース間の強い一貫性

  • 欠点:コード侵入、高結合

  • # シナリオ: 高い一貫性と無効性要件を備えたキャッシュ データ

  • #1.3 非同期通知
  • ##データベースが変更されたときにイベント通知を送信し、関連するサービスがそれをリッスンした後にキャッシュされたデータを変更します
    利点: 結合度が低く、複数のキャッシュ サービスに通知できます。同時に
  • 短所: 適時性が制限されており、キャッシュの不整合の問題が発生する可能性がある
  • ## シナリオ: 適時性は平均的で、複数のサービスが存在します。同期する必要があります
2. カナルベースの非同期通知

Java に基づいて Redis マルチレベル キャッシュを実装する方法

は Alibaba 傘下のオープン ソース プロジェクトで、Java 開発に基づいていますJava に基づいて Redis マルチレベル キャッシュを実装する方法

データベースの増分ログ分析に基づいて、増分データのサブスクリプションと消費を提供します
  • mysql に基づくマスター/スレーブ バックアップの考え方
  • 2.1 mysql マスター/スレーブ レプリケーション
  • 2.2 運河の動作原則

canalはMySQLスレーブをシミュレートする対話型プロトコル、MySQLスレーブのふりをしてダンププロトコルをMySQLマスターに送信しますJava に基づいて Redis マルチレベル キャッシュを実装する方法

MySQLマスターはダンプを受信しますリクエストを実行し、バイナリ ログをスレーブ (つまり canal) にプッシュし始めます。
  • canal はバイナリ ログ オブジェクト (元はバイト ストリーム) を解析します。

以上がJava に基づいて Redis マルチレベル キャッシュを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。