1. 程式人生 > 實用技巧 >「最強」Lettuce 已支援 Redis6 客戶端快取

「最強」Lettuce 已支援 Redis6 客戶端快取

Redis 客戶端快取

快取的解決方案一般有兩種:

【L1】 記憶體快取(如 Caffeine、Ehcache) —— 速度快,程序內可用,但重啟快取丟失,出現快取雪崩的問題。

【L2】集中式快取(如 Redis)—— 可同時為多節點提供服務,但高併發下,頻寬成為瓶頸。

業內有很多開源框架來解決以上問題,既能有 L1 速度,並且擁有 L2 叢集態。如下

J2Cache 兩級快取框架

hotkey 熱點資料實時同步

redis 6.0 版本中,已經預設支援了客戶端快取功能,Java 中主流的連線客戶端 lettuce 在最新的快照版本 (6.0.0.BUILD-SNAPSHOT) 已經提供支援。 下邊就通過程式碼來體驗一下客戶端快取的神奇功能。

Redis 6.0 安裝

安裝 redis 6,這裡通過 Docker 安裝命令如下

docker run --name redis6 -p 6379:6379 --restart=always -d redis:6.0.6

Jar 依賴

注意: 這裡使用 lettuce 客戶端,注意當前使用 6.0 的快照版本 ,需要在 pom 增加 lettuce 快照倉庫

  • 1.lettuce 6.0 快照依賴
<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
    <version>6.0.0.BUILD-SNAPSHOT</version>
</dependency>
    1. 配置快照倉庫
<repositories>
        <repository>
            <id>sonatype-snapshots</id>
            <name>Sonatype Snapshot Repository</name>
            <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

程式碼操作

  • 使用 lettuce 連線 redis ,並迴圈檢視 k1 的值
// <1> 建立單機連線的連線資訊
RedisURI redisUri = RedisURI.builder()                    //
        .withHost("127.0.0.1")
        .withPort(6379)
        .build();
RedisClient redisClient = RedisClient.create(redisUri);
StatefulRedisConnection<String, String> otherParty = redisClient.connect();
RedisCommands<String, String> commands = otherParty.sync();
StatefulRedisConnection<String, String> connection = redisClient.connect();
// <2> 建立快取訪問器
Map<String, String> clientCache = new ConcurrentHashMap<>(); //map 自動儲存所有操作key的 key=value
CacheFrontend<String, String> frontend = ClientSideCaching.enable(CacheAccessor.forMap(clientCache), connection,
        TrackingArgs.Builder.enabled());

// <3> 客戶端正常寫入測試資料 k1 v1
String key = "k1";
commands.set(key, "v1");
// <4> 迴圈讀取
while (true) {
    // <4.1> 快取訪問器中的值,檢視是否和 Redis 服務端同步
    String cachedValue = frontend.get(key);
    System.out.println("當前 k1 的值為:--->" + cachedValue);
    Thread.sleep(3000);
}
  • redis-cli 客戶端同時操作 k1 修改 k1 的值

./redis-cli -h 127.0.0.1 -p 6379

> set k1 v2
  • 注意檢視 控制檯日誌
...
當前 k1 的值為:--->v1
當前 k1 的值為:--->v1
當前 k1 的值為:--->v1
當前 k1 的值為:--->v2
當前 k1 的值為:--->v2
當前 k1 的值為:--->v2
....

如上: k1 的值在其他客戶端(redis-cli)修改,lettuce 客戶端確實感知到了資料變化。 但 lettuce 到底 CacheFrontend.get 到底有沒有查詢 redis 呢?

我們可以通過以下監控看下客戶端具體的操作細節

監控


./redis-cli -h 127.0.0.1 -p 6379

> MONITOR
OK
1595922453.165088 [0 172.16.1.96:57482] "SET" "k1" "v1"   # 對應 <3> 寫入測試資料
1595922453.168238 [0 172.16.1.96:57483] "GET" "k1"        # <4.1> 快取訪問器中的值,由於第一次查詢為空需要穿透去查詢 redis-server
1595922466.525942 [0 172.16.1.96:57498] "COMMAND"         # 其他客戶端 redis-cli 接入 提醒
1595922472.046488 [0 172.16.1.96:57498] "set" "k1" "v2"   # 其他客戶端 操作 k1
1595922474.208214 [0 172.16.1.96:57483] "GET" "k1"        # 由於k1 值發生變化,迴圈 <4.1> 會重新查詢redis-server

如上: 雖然是個死迴圈,但是關於 redis 操作只有以上註釋的幾條,說明客戶端快取生效。

總結

  • 當前僅有 lettuce 支援此功能,jedis 還未支援
  • spring-boot-data-redis 暫未支援此功能,估計需要 spring boot 2.5 版本

專案推薦: Spring Cloud 、Spring Security OAuth2的RBAC許可權管理系統 歡迎關注