一、Redis 集羣方案比較
1. 哨兵模式
在redis3.0以前的版本要實現集羣一般是藉助哨兵sentinel工具來監控master節點的狀態,如果master節點異常,則會做主從切換,將某一臺slave作爲master,哨兵的配置略微複雜,並且性能和高可用性等各方面表現一般,特別是在主從切換的瞬間存在訪問瞬斷的情況,而且哨兵模式只有一個主節點對外提供服務,沒法支持很高的併發,且單個主節點內存也不宜設置得過大,否則會導致持久化文件過大,影響數據恢復或主從同步的效率。
2. 高可用集羣模式
redis集羣是一個由多個主從節點羣組成的分佈式服務器羣,它具有複製、高可用和分片特性。Redis集羣不需要 sentinel哨兵也能完成節點移除和故障轉移的功能。需要將每個節點設置成集羣模式,這種集羣模式沒有中心節點,可 水平擴展,據官方文檔稱可以線性擴展到上萬個節點(官方推薦不超過1000個節點)。redis集羣的性能和高可用性均優於之前版本的哨兵模式,且集羣配置非常簡單 。
二、搭建步驟
由於時間和機器的緣故,本文演示的是三主三從的集羣架構,且只有三臺主機,每臺主機上模擬出一主一從。本人使用的Windows操作系統,使用VMWare來虛擬出三臺主機,Centos 7 操作系統,在安裝好第一臺主機後,第二臺和第三臺可以直接克隆第一臺。三臺機器 ip 分別爲:192.168.2.101、192.168.2.102、192.168.2.103。
1.redis 安裝
# 安裝gcc
yum install gcc
# 本人安裝在 /usr/local/ 目錄下,redis 最新版是6.0.5
cd /usr/local/
wget http://download.redis.io/releases/redis‐5.0.8.tar.gz
tar xzf redis‐5.0.8.tar.gz
cd redis‐5.0.8
make
# 啓動並指定配置文件
src/redis‐server redis.conf(使用後臺啓動,修改redis.conf裏的daemonize改爲yes)
# 驗證啓動是否成功
ps -ef | grep redis
# 進入redis客戶端
src/redis-cli -p 6379 (默認6379端口)
# 退出客戶端
quit
2.集羣搭建
第一步:在第一臺機器的/usr/local下創建文件夾redis‐cluster,然後在其下面分別創建2個文件夾如下
(1)mkdir ‐p /usr/local/redis‐cluster
(2)cd /usr/local/redis‐cluster
(3)mkdir 8001 8004
第二步:把redis‐5.0.8/redis.conf 配置文件copy到8001下,修改如下內容:
(1)daemonize yes
(2)port 8001(分別對每個機器的端口號進行設置)
(3)pidfile /var/run/redis_8001.pid
(4)logfile "8001.log"
(5)dir /usr/local/redis‐cluster/8001/(指定數據文件存放位置,必須要指定不同的目錄位置,不然會丟失數據)
(6)cluster‐enabled yes(啓動集羣模式)
(7)cluster‐config‐file nodes‐8001.conf(集羣節點信息文件,這裏800x好和port對應上)
(8)cluster‐node‐timeout 5000
(9)# bind 127.0.0.1(去掉bind綁定訪問ip信息)
(10) protected‐mode no (關閉保護模式)
(11) appendonly yes
如果要設置密碼需要增加如下配置:
(12) requirepass 123456 (設置redis訪問密碼)
(13) masterauth 123456 (設置集羣節點間訪問密碼,跟上面一致)
第三步:把修改後的配置文件,copy到8004,修改第2、3、5項裏的端口號,可以用批量替換:
:%s/源字符串/目的字符串/g
第四步:另外兩臺機器也需要做上面幾步操作,第二臺機器用8002和8005,第三臺機器用8003和8006
第五步:分別啓動6個redis實例,然後檢查是否啓動成功
(1)/usr/local/redis-5.0.8/src/redis-server /usr/local/redis-cluster/800*/redis.conf
(2)ps ‐ef | grep redis 查看是否啓動成功
第六步:用redis‐cli創建整個redis集羣(redis5以前的版本集羣是依靠ruby腳本redis‐trib.rb實現)
# 下面命令裏的1代表爲每個創建的主服務器節點創建一個從服務器節點
# 執行這條命令需要確認三臺機器之間的redis實例要能相互訪問,可以先簡單把所有機器防火牆關掉,如果不關閉防火牆 則需要打開redis服務端口和集羣節點gossip通信端口
# 關閉防火牆
# systemctl stop firewalld # 臨時關閉防火牆
# systemctl disable firewalld # 禁止開機啓動
(1)/usr/local/redis-5.0.8/src/redis-cli -a 123456 --cluster create --cluster-replicas 1 192.168.2.101:8001 192.168.2.102:8002 192.168.2.103:8003 192.168.2.101:8004 192.168.2.102:8005 192.168.2.103:8006
第七步:驗證集羣:
(1)連接任意一個客戶端即可:./redis-cli -c -h -p (‐a訪問服務端密碼,‐c表示集羣模式,指定ip地址和端口號)
如:/usr/local/redis-5.0.8/src/redis-cli -a 123456 -h 192.168.2.101 -p 8001 -c (-c 代表以集羣模式連接,可省略)
(2)進行驗證: cluster info(查看集羣信息)、cluster nodes(查看節點列表)
(3)進行數據操作驗證
(4)關閉集羣則需要逐個進行關閉,使用命令:
/usr/local/redis-5.0.8/src/redis-cli -a 123456 -c -h 192.168.2.102 -p 8002 shutdown
創建集羣成功後可看到看到如下信息:
連接客戶端: /usr/local/redis-5.0.8/src/redis-cli -a 123456 -h 192.168.2.101 -p 8001
執行 cluster info 可看到如下信息:
執行 cluster nodes 可看到如下信息:
最前面一串類似uuid的爲節點id,slave節點中間也有這麼一串,代表的是他的master節點id。
三、Spring Boot 項目整合 Redis
- 創建 Spring Boot 項目,引入核心依賴:
<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>
- 修改 application.properties 配置:
spring.redis.timeout=3000 spring.redis.password=123456 spring.redis.lettuce.pool.max-active=1000 spring.redis.lettuce.pool.min-idle=10 spring.redis.lettuce.pool.max-idle=50 spring.redis.lettuce.pool.max-wait=1000 # springboot2.3 以後加上下面配置可自動刷新拓撲,某節點掛掉後,會有新的主從關係,如果不配置,調用接口時程序會報錯 spring.redis.lettuce.cluster.refresh.adaptive=true spring.redis.lettuce.cluster.refresh.period=5000 # spring.redis.sentinel.master=mymaster # spring.redis.sentinel.nodes=192.168.2.101:26379,192.168.2.101:26380,192.168.2.101:26381 spring.redis.cluster.nodes=192.168.2.101:8001,192.168.2.102:8002,192.168.2.103:8003,192.168.2.101:8004,192.168.2.102:8005,192.168.2.103:8006
- 創建 Controller ,如下:
/** * @author: francis * @description: * @date: 2020/6/21 21:24 */ @RestController public class IndexController { private final StringRedisTemplate stringRedisTemplate; public IndexController(StringRedisTemplate stringRedisTemplate) { this.stringRedisTemplate = stringRedisTemplate; } @RequestMapping("/test") public String test(@RequestParam("key") String key, @RequestParam("value") String value) { stringRedisTemplate.opsForValue().set(key, value); return stringRedisTemplate.opsForValue().get(key); } }
- 運行程序,訪問接口
- 連接 redis 客戶端: /usr/local/redis-5.0.8/src/redis-cli -a 123456 -h 192.168.2.103 -p 8006 ,查看剛剛設置的key-value
Redis Cluster 將所有數據劃分爲 16384 個 slots(槽位),每個節點負責其中一部分槽位。槽位的信息存儲於每個節點中。
當 Redis Cluster 的客戶端來連接集羣時,它也會得到一份集羣的槽位配置信息並將其緩存在客戶端本地。這樣當客戶端要查找某個 key 時,可以直接定位到目標節點。同時因爲槽位的信息可能會存在客戶端與服務器不一致的情況,還需要糾正機制來實現槽位信息的校驗調整。
槽位定位算法
Cluster 默認會對 key 值使用 crc16 算法進行 hash 得到一個整數值,然後用這個整數值對 16384 進行取模來得到具體槽位。
HASH_SLOT = CRC16(key) mod 16384
四、Redis 集羣相關命令
-
幫助命令
/usr/local/redis-5.0.8/src/redis-cli -a 123456 --cluster help
-
命令含義
1.create:創建集羣 host1:port1 ... hostN:portN 2.call:可以執行redis命令 3.add-node:將一個節點添加到集羣裏,第一個參數爲新節點的ip:port,第二個參數爲集羣中任意一個已經存在的節點的ip:port 4.del-node:移除節點 5.reshard:重新分片 6.check:檢查集羣狀態
五、Redis 集羣水平擴展
-
查看redis集羣信息,結果如下:
目前是三主三從,現在再增加一主一從,在101機器上新增8007和8008節點。 -
mkdir /usr/local/redis-cluster/8007 mkdir /usr/local/redis-cluster/8008
-
分別拷貝 8001 節點目錄下的 redis.conf 至 8007 和 8008 節點目錄下
-
修改redis.conf,和前面搭建步驟一樣,批量替換端口號::%s/源字符串/目的字符串/g 來替換端口號
-
啓動新增節點: /usr/local/redis-5.0.8/src/redis-server /usr/local/redis-cluster/800*/redis.conf
-
查看是否啓動成功: ps -ef | grep redis
-
添加8007節點,默認爲主節點:
# 前面的ip:port爲新增節點,後面的ip:port爲已知存在節點 /usr/local/redis-5.0.8/src/redis-cli -a 123456 --cluster add-node 192.168.2.101:8007 192.168.2.101:8001
-
再次查看集羣信息,發現新增master節點8007,但是沒有分配任何的slot(hash槽),
-
爲8007節點分配hash槽
/usr/local/redis-5.0.8/src/redis-cli -a 123456 --cluster reshard 192.168.2.101:8007 # 執行完這條命令會提示需要輸入幾個參數,具體如下圖
-
再次查看節點信息,8007節點分配槽位成功
-
將 8008 添加進集羣
/usr/local/redis-5.0.8/src/redis-cli -a 123456 --cluster add-node 192.168.2.101:8008 192.168.2.101:8001
-
查看集羣信息
-
將 8008 節點配置爲 8007 節點的從節點
1. /usr/local/redis-5.0.8/src/redis-cli -a 123456 -h 192.168.2.101 -p 8008 2. cluster replicate 44a88ac96d18be2db5b962fcca1602af0043ddcf
六、Redis 集羣節點移除
基於第五章節,移除8007和8008節點。
-
移除8008節點(移除此節點會將該節點shutdown)
/usr/local/redis-5.0.8/src/redis-cli -a 123456 --cluster del-node 192.168.2.101:8008 6d29ebf9db5e9e5bb0faaacb4bc27bc0732340a7
-
查看集羣信息
-
移除8007節點,8007節點是master節點,需要將數據遷移,所以需要重新分配槽位,否則數據將丟失。示例是將8007節點遷移至8001節點
/usr/local/redis-5.0.8/src/redis-cli -a 123456 --cluster reshard 192.168.2.101:8007
-
爲確保遷移成功,再次查看集羣信息
-
移除8007節點
/usr/local/redis-5.0.8/src/redis-cli -a 123456 --cluster del-node 192.168.2.101:8007 44a88ac96d18be2db5b962fcca1602af0043ddcf