首頁  >  文章  >  Java  >  基於Java怎麼實作Redis多層緩存

基於Java怎麼實作Redis多層緩存

WBOY
WBOY轉載
2023-05-13 19:52:171030瀏覽

一、多層快取

1. 傳統快取方案

請求到達tomcat後,先去redis中取得緩存,不命中則去mysql取得

基於Java怎麼實作Redis多層緩存

2. 多層快取方案

  • tomcat的請求並發數,是遠小於redis的,因此tomcat會變成瓶頸

  • 利用請求處理每個環節,分別加入緩存,減輕tomcat壓力,提升服務效能

基於Java怎麼實作Redis多層緩存

# #二、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"));
        }
    }
  • 三、快取一致性

1. 常見方案

1.1 設定有效期限

    給緩存設定有效期,到期後自動刪除。再次查詢時可以更新
  • 優點:簡單,方便
  • #缺點:時效性差,快取過期之前可能不一致
  • 場景:更新頻率低,時效性需求比較低的業務
  • 1.2 同步雙寫
    在修改資料庫的同時,直接修改快取
  • 優點:有程式碼侵入,快取與資料庫強一致性
  • ##缺點:程式碼進入,耦合性高
  • 場景:對一致性,失效性要求較高的快取資料
  • 1.3 非同步通知
修改資料庫時發送事件通知,相關服務監聽到後修改快取資料
  • 優勢:低耦合,可以同時通知多個快取服務
  • 缺點:時效性一把,可能有快取不一致問題
  • 場景:時效性一般,有多個服務需要同步

基於Java怎麼實作Redis多層緩存

2. 基於Canal的非同步通知基於Java怎麼實作Redis多層緩存

是阿里旗下的一個開源項目,基於java開發
  • 基於資料庫增量日誌解析,提供增量資料訂閱和消費
  • 基於mysql的主從備份的想法
  • 2.1 mysql主從複製

#2.2 canal 工作原理基於Java怎麼實作Redis多層緩存

canal 模擬MySQL slave 的互動協議,偽裝自己為MySQL slave ,向MySQL master 發送dump 協議
  • MySQL master 收到dump 請求, 開始推送binary log 給slave (即canal )
  • canal 解析binary log 物件(原始為byte 流)
  • #

以上是基於Java怎麼實作Redis多層緩存的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除