008.Redis

特別說明: 本人平時(shí)混跡于 B 站邑雅,不咋回復(fù)這里的評(píng)論,有問題可以到 B 站視頻評(píng)論區(qū)留言找我
視頻地址: https://space.bilibili.com/31137138/favlist?fid=326428938
課件說明: 本次提供的課件是 Spring Cloud Netflix 版微服務(wù)架構(gòu)指南山卦,如果有興趣想要學(xué)習(xí) Spring Cloud Alibaba 版铲敛,可以前往 http://www.qfdmy.com 查看相關(guān)課程資源
案例代碼: https://github.com/topsale/hello-spring-cloud-netflix

什么是 Redis

Redis 是用 C 語言開發(fā)的一個(gè)開源的高性能鍵值對(duì)(key-value)數(shù)據(jù)庫。它通過提供多種鍵值數(shù)據(jù)類型來適應(yīng)不同場(chǎng)景下的存儲(chǔ)需求

Redis 的特點(diǎn)

  • Redis 支持?jǐn)?shù)據(jù)持久化疮胖,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤中亲善,重啟的時(shí)候可以再次加載進(jìn)行使用
  • Redis 不僅僅支持簡(jiǎn)單的 KV 類型的數(shù)據(jù)设易,同時(shí)還提供 listset蛹头,zset顿肺,hash 等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)
  • Redis 支持?jǐn)?shù)據(jù)的備份,即 Master - Slave 模式的數(shù)據(jù)備份

Redis 的優(yōu)勢(shì)

  • 性能極高: Redis 讀的速度是 110000 次/s, 寫的速度是 81000 次/s
  • 豐富的數(shù)據(jù)類型: Redis 支持 Strings, Lists, Hashes, SetsOrdered Sets 數(shù)據(jù)類型操作
  • 原子性: Redis 的所有操作都是原子性的渣蜗,意思就是要么成功執(zhí)行要么失敗完全不執(zhí)行屠尊。單個(gè)操作是原子性的。多個(gè)操作也支持事務(wù)耕拷,即原子性讼昆,通過 MULTIEXEC 指令包起來
  • 其它特性:Redis 還支持 發(fā)布/訂閱,Key 過期設(shè)置等

Redis 的應(yīng)用場(chǎng)景

  • 緩存(數(shù)據(jù)查詢骚烧、短連接控淡、新聞內(nèi)容、商品內(nèi)容等等)
  • 分布式集群架構(gòu)中的 Session 分離
  • 聊天室的在線好友列表
  • 任務(wù)隊(duì)列(秒殺止潘、搶購、12306 等等)
  • 應(yīng)用排行榜
  • 網(wǎng)站訪問統(tǒng)計(jì)
  • 數(shù)據(jù)過期處理(可以精確到毫秒)
  • 分布式協(xié)調(diào)(分布式鎖)

Redis 高可用集群

HA(High Available辫诅,高可用性群集)機(jī)集群系統(tǒng)簡(jiǎn)稱凭戴,是保證業(yè)務(wù)連續(xù)性的有效解決方案,一般有兩個(gè)或兩個(gè)以上的節(jié)點(diǎn)炕矮,且分為活動(dòng)節(jié)點(diǎn)及備用節(jié)點(diǎn)么夫。通常把正在執(zhí) 行業(yè)務(wù)的稱為活動(dòng)節(jié)點(diǎn)者冤,而作為活動(dòng)節(jié)點(diǎn)的一個(gè)備份的則稱為備用節(jié)點(diǎn)。當(dāng)活動(dòng)節(jié)點(diǎn)出現(xiàn)問題档痪,導(dǎo)致正在運(yùn)行的業(yè)務(wù)(任務(wù))不能正常運(yùn)行時(shí)涉枫,備用節(jié)點(diǎn)此時(shí)就會(huì)偵測(cè)到,并立即接續(xù)活動(dòng)節(jié)點(diǎn)來執(zhí)行業(yè)務(wù)腐螟。從而實(shí)現(xiàn)業(yè)務(wù)的不中斷或短暫中斷愿汰。

Redis 一般以主/從方式部署(這里討論的應(yīng)用從實(shí)例主要用于備份,主實(shí)例提供讀寫)該方式要實(shí)現(xiàn) HA 主要有如下幾種方案:

  • keepalived: 通過 keepalived 的虛擬 IP乐纸,提供主從的統(tǒng)一訪問衬廷,在主出現(xiàn)問題時(shí), 通過 keepalived 運(yùn)行腳本將從提升為主汽绢,待主恢復(fù)后先同步后自動(dòng)變?yōu)橹髀鸢希摲桨傅暮锰幨侵鲝那袚Q后,應(yīng)用程序不需要知道(因?yàn)樵L問的虛擬 IP 不變)宁昭,壞處是引入 keepalived 增加部署復(fù)雜性跌宛,在有些情況下會(huì)導(dǎo)致數(shù)據(jù)丟失
  • zookeeper: 通過 zookeeper 來監(jiān)控主從實(shí)例, 維護(hù)最新有效的 IP积仗, 應(yīng)用通過 zookeeper 取得 IP疆拘,對(duì) Redis 進(jìn)行訪問,該方案需要編寫大量的監(jiān)控代碼
  • sentinel: 通過 Sentinel 監(jiān)控主從實(shí)例斥扛,自動(dòng)進(jìn)行故障恢復(fù)入问,該方案有個(gè)缺陷:因?yàn)橹鲝膶?shí)例地址( IP & PORT )是不同的,當(dāng)故障發(fā)生進(jìn)行主從切換后稀颁,應(yīng)用程序無法知道新地址芬失,故在 Jedis2.2.2 中新增了對(duì) Sentinel 的支持,應(yīng)用通過 redis.clients.jedis.JedisSentinelPool.getResource() 取得的 Jedis 實(shí)例會(huì)及時(shí)更新到新的主實(shí)例地址
20150620161606990.jpg

注意: sentinel 是解決 HA 問題的匾灶,cluster 是解決主從復(fù)制問題的棱烂,不重復(fù),并且經(jīng)常一起用

Redis Sentinel

Redis 集群可以在一組 redis 節(jié)點(diǎn)之間實(shí)現(xiàn)高可用性和 sharding阶女。在集群中會(huì)有 1 個(gè) master 和多個(gè) slave 節(jié)點(diǎn)颊糜。當(dāng) master 節(jié)點(diǎn)失效時(shí),應(yīng)選舉出一個(gè) slave 節(jié)點(diǎn)作為新的 master秃踩。然而 Redis 本身 (包括它的很多客戶端) 沒有實(shí)現(xiàn)自動(dòng)故障發(fā)現(xiàn)并進(jìn)行主備切換的能力衬鱼,需要外部的監(jiān)控方案來實(shí)現(xiàn)自動(dòng)故障恢復(fù)。

Redis Sentinel 是官方推薦的高可用性解決方案憔杨。它是 Redis 集群的監(jiān)控管理工具鸟赫,可以提供節(jié)點(diǎn)監(jiān)控、通知、自動(dòng)故障恢復(fù)和客戶端配置發(fā)現(xiàn)服務(wù)抛蚤。

18841d5327556bfa750148943011901d1eac3cd8.jpg

基于 Docker 安裝 Redis 集群

2018 年 10 月 Redis 發(fā)布了穩(wěn)定版本的 5.0 版本台谢,推出了各種新特性,其中一點(diǎn)是放棄 Ruby 的集群方式岁经,改為 使用 C 語言編寫的 redis-cli 的方式朋沮,使集群的構(gòu)建方式復(fù)雜度大大降低

  • 下載所需鏡像
docker pull redis
docker pull zvelo/redis-trib
  • 創(chuàng)建配置文件

官方配置文件地址:http://download.redis.io/redis-stable/redis.conf ,我們部署 3 個(gè)節(jié)點(diǎn)缀壤,需要分別創(chuàng)建 3 個(gè)配置文件樊拓,路徑如下

renode1:`cluster/node1/redis.conf`
renode2:`cluster/node2/redis.conf`
renode3:`cluster/node3/redis.conf`

配置文件內(nèi)容如下 (端口號(hào)不要重復(fù))

bind 0.0.0.0
# 關(guān)閉保護(hù)模式
protected-mode no
# 綁定自定義端口
port 6379
# 禁止 Redis 后臺(tái)運(yùn)行
# daemonize yes
pidfile /var/run/redis_6379.pid
# 開啟集群
cluster-enabled yes
# 集群的配置,配置文件首次啟動(dòng)自動(dòng)生成
cluster-config-file nodes_6379.conf
# 開啟 AOF
appendonly yes
# 集群的 IP
cluster-announce-ip 192.168.x.x
# 集群的端口
cluster-announce-port 6379
# 集群的總線端口
cluster-announce-bus-port 16379
  • 創(chuàng)建資源配置

docker-compose.yml 配置文件如下

version: '3.1'
services:
  renode1:
    image: redis
    container_name: renode1
    restart: always
    ports:
      - 6379:6379
      - 16379:16379
    volumes:
      - ./cluster/node1:/usr/local/etc/redis
    command:
      redis-server /usr/local/etc/redis/redis.conf
  renode2:
    image: redis
    container_name: renode2
    restart: always
    ports:
      - 6380:6380
      - 16380:16380
    volumes:
      - ./cluster/node2:/usr/local/etc/redis
    command:
      redis-server /usr/local/etc/redis/redis.conf
  renode3:
    image: redis
    container_name: renode3
    restart: always
    ports:
      - 6381:6381
      - 16381:16381
    volumes:
      - ./cluster/node3:/usr/local/etc/redis
    command:
      redis-server /usr/local/etc/redis/redis.conf
docker-compose up -d
  • 創(chuàng)建集群
docker run --rm -it zvelo/redis-trib create 192.168.141.220:6379 192.168.141.220:6380 192.168.141.220:6381

# 輸出如下
>>> Creating cluster
>>> Performing hash slots allocation on 3 nodes...
Using 3 masters:
192.168.141.220:6379
192.168.141.220:6380
192.168.141.220:6381
M: 9250c85592b7bb8a19636b90e4cf22590bd3334f 192.168.141.220:6379
   slots:0-5460 (5461 slots) master
M: 7373de7b44ee50a1e4f653bfba1bb808138e7e3a 192.168.141.220:6380
   slots:5461-10922 (5462 slots) master
M: ec7e6e4cdd142249e3aa83541044932655d75b66 192.168.141.220:6381
   slots:10923-16383 (5461 slots) master
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join..
>>> Performing Cluster Check (using node 192.168.141.220:6379)
M: 9250c85592b7bb8a19636b90e4cf22590bd3334f 192.168.141.220:6379
   slots:0-5460 (5461 slots) master
M: 7373de7b44ee50a1e4f653bfba1bb808138e7e3a 192.168.141.220:6380
   slots:5461-10922 (5462 slots) master
M: ec7e6e4cdd142249e3aa83541044932655d75b66 192.168.141.220:6381
   slots:10923-16383 (5461 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

驗(yàn)證 Redis 集群是否成功

  • 交互式進(jìn)入容器
docker exec -it renode1 /bin/bash
  • 登錄 Redis
redis-cli -p 6379
  • 查看集群信息
127.0.0.1:6379> cluster info

# 輸出如下
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:3
cluster_size:3
cluster_current_epoch:3
cluster_my_epoch:1
cluster_stats_messages_ping_sent:860
cluster_stats_messages_pong_sent:870
cluster_stats_messages_sent:1730
cluster_stats_messages_ping_received:868
cluster_stats_messages_pong_received:860
cluster_stats_messages_meet_received:2
cluster_stats_messages_received:1730
  • 查看集群節(jié)點(diǎn)
127.0.0.1:6379> cluster nodes

# 輸出如下
ec7e6e4cdd142249e3aa83541044932655d75b66 192.168.141.220:6381@16381 master - 0 1569665070102 3 connected 10923-16383
7373de7b44ee50a1e4f653bfba1bb808138e7e3a 192.168.141.220:6380@16380 master - 0 1569665069094 2 connected 5461-10922
9250c85592b7bb8a19636b90e4cf22590bd3334f 192.168.141.220:6379@16379 myself,master - 0 1569665069000 1 connected 0-5460
  • 查看集群插槽
127.0.0.1:6379> cluster slots

# 輸出如下
1) 1) (integer) 10923
   2) (integer) 16383
   3) 1) "192.168.141.220"
      2) (integer) 6381
      3) "ec7e6e4cdd142249e3aa83541044932655d75b66"
2) 1) (integer) 5461
   2) (integer) 10922
   3) 1) "192.168.141.220"
      2) (integer) 6380
      3) "7373de7b44ee50a1e4f653bfba1bb808138e7e3a"
3) 1) (integer) 0
   2) (integer) 5460
   3) 1) "192.168.141.220"
      2) (integer) 6379
      3) "9250c85592b7bb8a19636b90e4cf22590bd3334f"

基于 Docker 安裝 Redis Sentinel

  • 創(chuàng)建配置文件

我們部署 3 個(gè) Sentinel 節(jié)點(diǎn)诉位,需要分別創(chuàng)建 3 個(gè)配置文件骑脱,路徑如下

resentinel1:`cluster/node1/sentinel.conf`
resentinel2:`cluster/node2/sentinel.conf`
resentinel3:`cluster/node3/sentinel.conf`

配置文件內(nèi)容如下 (端口號(hào)不要重復(fù))

bind 0.0.0.0
port 26379
dir /tmp
# 自定義集群名,其中 192.168.141.220 為 Redis Master 的 IP苍糠,6379 為 Redis Master 的端口叁丧,2 為最小投票數(shù)(因?yàn)橛?3 臺(tái) Sentinel 所以可以設(shè)置成 2)
sentinel monitor rmaster 192.168.141.220 6379 2
sentinel down-after-milliseconds rmaster 30000
sentinel parallel-syncs rmaster 1
sentinel failover-timeout rmaster 180000
sentinel deny-scripts-reconfig yes
  • 創(chuàng)建資源配置

docker-compose.yml 配置文件如下

version: '3.1'
services:
  resentinel1:
    image: redis
    container_name: resentinel1
    ports:
      - 26379:26379
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    volumes:
      - ./cluster/node1/sentinel.conf:/usr/local/etc/redis/sentinel.conf
  resentinel2:
    image: redis
    container_name: resentinel2
    ports:
      - 26380:26380
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    volumes:
      - ./cluster/node2/sentinel.conf:/usr/local/etc/redis/sentinel.conf
  resentinel3:
    image: redis
    container_name: resentinel3
    ports:
      - 26381:26381
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    volumes:
      - ./cluster/node3/sentinel.conf:/usr/local/etc/redis/sentinel.conf

驗(yàn)證 Sentinel 集群是否成功

  • 交互式進(jìn)入容器
docker exec -it resentinel1 /bin/bash
  • 登錄 Redis Sentinel
redis-cli -p 26379
  • 查看集群 Master 信息
127.0.0.1:26379> sentinel master rmaster

# 輸出如下
 1) "name"
 2) "rmaster"
 3) "ip"
 4) "192.168.141.220"
 5) "port"
 6) "6379"
 7) "runid"
 8) "30055483aeb9d75f35c0046aaec03440731e3e88"
 9) "flags"
10) "master"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "413"
19) "last-ping-reply"
20) "413"
21) "down-after-milliseconds"
22) "30000"
23) "info-refresh"
24) "2878"
25) "role-reported"
26) "master"
27) "role-reported-time"
28) "143537"
29) "config-epoch"
30) "0"
31) "num-slaves"
32) "0"
33) "num-other-sentinels"
34) "2"
35) "quorum"
36) "2"
37) "failover-timeout"
38) "180000"
39) "parallel-syncs"
40) "1"

Redis 數(shù)據(jù)類型

Redis 支持 5 種數(shù)據(jù)類型

  • string(字符串)
  • hash(哈希)
  • list(列表)
  • set(集合)
  • zset(sorted set:有序集合)

字符串

  • string 是 Redis 最基本的數(shù)據(jù)類型。一個(gè) key 對(duì)應(yīng)一個(gè) value
  • string 是二進(jìn)制安全的岳瞭。也就是說 Redis 的 string 可以包含任何數(shù)據(jù)拥娄。比如圖片或者序列化的對(duì)象
  • string 類型的值最大能存儲(chǔ) 512MB
  • string 類似于 Java 中的 Map,一個(gè) key 對(duì)應(yīng)一個(gè) value
15593451-e46db8d61d8c41aa.jpg

哈希

  • Redis hash 是一個(gè)鍵值對(duì)(key - value)集合
  • Redis hash 是一個(gè) string 類型的 keyvalue 的映射表瞳筏,hash 特別適合用于存儲(chǔ)對(duì)象
  • 可以將 Redis hash 看成一個(gè) KV 的集合稚瘾。也可以將其想成一個(gè) hash 對(duì)應(yīng)著多個(gè) string
15593451-43d6c27ce64dffe1.jpg

列表

Redis 列表是簡(jiǎn)單的字符串列表,按照插入順序排序姚炕。我們可以往列表的左邊或者右邊添加元素摊欠, list 就是一個(gè)簡(jiǎn)單的字符串集合,和 Java 中的 list 相差不大柱宦,區(qū)別就是這里的 list 存放的是字符串 (list 內(nèi)的元素是可重復(fù)的)

15593451-948582ab93a858ce.jpg

集合

Redis 的 set 是字符串類型的無序集合些椒。集合是通過哈希表實(shí)現(xiàn)的,因此添加掸刊、刪除免糕、查找的復(fù)雜度都是 o(1),Redis 的 set 是一個(gè) key 對(duì)應(yīng)著多個(gè)字符串類型的 value忧侧,也是一個(gè)字符串類型的集合石窑,但是和 Redis 的 list 不同的是 set 中的字符串集合元素不能重復(fù),但是 list 可以

有序集合

Redis zset 和 set 一樣都是字符串類型元素的集合蚓炬,并且集合內(nèi)的元素不能重復(fù)松逊;不同的是,zset 每個(gè)元素都會(huì)關(guān)聯(lián)一個(gè) double 類型的分?jǐn)?shù)肯夏。redis 通過分?jǐn)?shù)來為集合中的成員進(jìn)行從小到大的排序

15593451-cf97abbc9867a7fd.jpg

zset 的元素是唯一的棺棵,但是分?jǐn)?shù)(score)卻可以重復(fù)

Spring Boot 整合 Redis

添加依賴

  • 主要依賴
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-pool2</artifactId>
</dependency>
  • 因?yàn)橐c數(shù)據(jù)庫結(jié)合使用楼咳,以 provider-admin-service 項(xiàng)目為例,一并提供完整依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.funtl</groupId>
        <artifactId>provider</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>provider-admin-service</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <!-- Spring Boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Spring Boot Data -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <!-- Spring Cloud -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <!-- Database -->
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.tomcat</groupId>
                    <artifactId>tomcat-jdbc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
        </dependency>

        <!-- Commons -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.funtl.hello.spring.cloud.provider.ProviderAdminApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

添加配置

  • 主要配置
spring:
  redis:
    cluster:
      nodes: 192.168.141.206:6379,192.168.141.206:6380,192.168.141.206:6381
    lettuce:
      # 連接池配置
      pool:
        # 連接池中的最小空閑連接烛恤,默認(rèn) 0
        min-idle: 0
        # 連接池中的最大空閑連接,默認(rèn) 8
        max-idle: 8
        # 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒有限制)余耽,默認(rèn) -1ms
        max-wait: -1ms
        # 連接池最大連接數(shù)(使用負(fù)值表示沒有限制)缚柏,默認(rèn) 8
        max-active: 8
  • 完整配置
spring:
  main:
    allow-bean-definition-overriding: true
  application:
    name: provider-admin
  zipkin:
    base-url: http://192.168.141.204:9411
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.141.206:8066/myshop?useUnicode=true&characterEncoding=utf-8&serverTimezone=Hongkong&useSSL=false
    username: root
    password: 123456
    hikari:
      minimum-idle: 5
      idle-timeout: 600000
      maximum-pool-size: 10
      auto-commit: true
      pool-name: MyHikariCP
      max-lifetime: 1800000
      connection-timeout: 30000
      connection-test-query: SELECT 1
  redis:
    cluster:
      nodes: 192.168.141.206:6379,192.168.141.206:6380,192.168.141.206:6381
    lettuce:
      pool:
        min-idle: 0
        max-idle: 8
        max-wait: -1ms
        max-active: 8

server:
  port: 11000

eureka:
  instance:
    hostname: localhost
  client:
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:8761/eureka/

mybatis:
  type-aliases-package: com.funtl.hello.spring.cloud.provider.domain
  mapper-locations: classpath:mapper/*.xml

客戶端工具類

注意: 我們使用 Spring 官方推薦的 Lettuce 客戶端工具不再采用 Jedis,原因是

  • 效率優(yōu)于 Jedis
  • 目前 Jedis 只支持單機(jī)
  • Jedis setNx 和設(shè)置過期時(shí)間是不同步的碟贾,在某些極端的情況下會(huì)發(fā)生死鎖币喧,導(dǎo)致程序崩潰(如果沒有設(shè)置 value, 線程 1 可能會(huì)釋放線程 2 的鎖)

注意: 由于代碼量較大會(huì)導(dǎo)致《簡(jiǎn)書》頁面無法正常顯示,請(qǐng)移步 LettuceUtils.java

  • 通過 Spring 容器注入即可使用
package com.funtl.hello.spring.cloud.provider.cache;

import com.funtl.hello.spring.cloud.commons.cache.LettuceUtils;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

@SpringBootTest
public class LettuceUtilsTests {

    @Resource
    private LettuceUtils lettuceUtils;

    @Test
    public void testSet() {
        lettuceUtils.set("name", "李小紅");
    }

    @Test
    public void testGet() {
        System.out.println(lettuceUtils.get("name"));
    }

    @Test
    public void testDelete() {
        lettuceUtils.delete("name");
    }
}

特別說明: 本人平時(shí)混跡于 B 站袱耽,不咋回復(fù)這里的評(píng)論杀餐,有問題可以到 B 站視頻評(píng)論區(qū)留言找我
視頻地址: https://space.bilibili.com/31137138/favlist?fid=326428938
課件說明: 本次提供的課件是 Spring Cloud Netflix 版微服務(wù)架構(gòu)指南禀忆,如果有興趣想要學(xué)習(xí) Spring Cloud Alibaba 版嫉沽,可以前往 http://www.qfdmy.com 查看相關(guān)課程資源
案例代碼: https://github.com/topsale/hello-spring-cloud-netflix

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市位衩,隨后出現(xiàn)的幾起案子冀续,更是在濱河造成了極大的恐慌琼讽,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件洪唐,死亡現(xiàn)場(chǎng)離奇詭異钻蹬,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)凭需,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門问欠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人粒蜈,你說我怎么就攤上這事顺献。” “怎么了薪伏?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵滚澜,是天一觀的道長。 經(jīng)常有香客問我嫁怀,道長设捐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任塘淑,我火速辦了婚禮萝招,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘存捺。我一直安慰自己槐沼,他們只是感情好曙蒸,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著岗钩,像睡著了一般纽窟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上兼吓,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天臂港,我揣著相機(jī)與錄音,去河邊找鬼视搏。 笑死审孽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的浑娜。 我是一名探鬼主播佑力,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼筋遭!你這毒婦竟也來了打颤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤宛畦,失蹤者是張志新(化名)和其女友劉穎瘸洛,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體次和,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡反肋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了踏施。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片石蔗。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖畅形,靈堂內(nèi)的尸體忽然破棺而出养距,到底是詐尸還是另有隱情,我是刑警寧澤日熬,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布棍厌,位于F島的核電站,受9級(jí)特大地震影響竖席,放射性物質(zhì)發(fā)生泄漏耘纱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一毕荐、第九天 我趴在偏房一處隱蔽的房頂上張望束析。 院中可真熱鬧,春花似錦憎亚、人聲如沸员寇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蝶锋。三九已至陆爽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扳缕,已是汗流浹背墓陈。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留第献,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓兔港,卻偏偏與公主長得像庸毫,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子衫樊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容