Redis 高可用性解決方案之哨兵與集群
點擊上方“程序員大白”,選擇“星標”公眾號
重磅干貨,第一時間送達

前言
在開始本章的講解之前,我們首先從宏觀角度回顧一下 Redis 實現(xiàn)高可用相關(guān)的技術(shù)。它們包括:持久化、復(fù)制、哨兵和集群,在本系列的前篇文章介紹了持久化以及復(fù)制的原理以及實現(xiàn)。本文將對剩下的兩種高可用技術(shù)哨兵、集群進行講解,講一講它們是如何進一步提高系統(tǒng)的高可用性?
Redis 的主從復(fù)制模式下,一旦主節(jié)點由于故障不能提供服務(wù),需要手動將從節(jié)點晉升為主節(jié)點,同時還要通知客戶端更新主節(jié)點地址,這種故障處理方式從一定程度上是無法接受的。Redis 2.8 以后提供了 Redis Sentinel 哨兵機制來解決這個問題。
在 Redis 3.0 之前,使用哨兵(sentinel)機制來監(jiān)控各個節(jié)點之間的狀態(tài)。Redis Cluster 是 Redis 的分布式解決方案,在 3.0 版本正式推出,有效地解決了 Redis 在分布式方面的需求。當遇到單機內(nèi)存、并發(fā)、流量等瓶頸時,可以采用 Cluster 架構(gòu)方案達到負載均衡的目的。
Redis HA 實踐(Redis Sentinel)
Redis Sentinel 概述
Sentinel(哨崗、哨兵)是 Redis 的高可用(high availability)解決方案:由一個或多個 Sentinel 實例(instance)組成的 Sentinel 系統(tǒng)(system)可以監(jiān)視任意多個主服務(wù)器,以及這些主服務(wù)器屬下的所有從服務(wù)器,并在被監(jiān)視的主服務(wù)器進入下線狀態(tài)時,自動將下線主服務(wù)器屬下的某個從服務(wù)器升級為新的主服務(wù)器,然后由新的主服務(wù)器代替已下線的主服務(wù)器繼續(xù)處理命令請求。


當 server1 的下線時長超過用戶設(shè)定的下線時長上限時,Sentinel 系統(tǒng)就會對 server1 執(zhí)行故障轉(zhuǎn)移操作:
首先,Sentinel 系統(tǒng)會挑選 server1 屬下的其中一個從服務(wù)器,并將這個被選中的從服務(wù)升級為新的主服務(wù)器。
之后,Sentinel 系統(tǒng)會向 server1 屬下的所有從服務(wù)器發(fā)送新的復(fù)制指令,讓他們成為新的主服務(wù)器的從服務(wù)器,當所有從服務(wù)器都開始復(fù)制新的主服務(wù)器時,故障轉(zhuǎn)移操作執(zhí)行完畢。
另外,Sentinel 還會繼續(xù)監(jiān)視已下線的 server1,并在它重新上線時,將它設(shè)置為新的主服務(wù)器的從服務(wù)器。
Sentinel 系統(tǒng)用于管理多個 Redis 服務(wù)器(instance), 該系統(tǒng)執(zhí)行以下三個任務(wù):
監(jiān)控(Monitoring):Sentinel 會不斷地檢查你的主服務(wù)器和從服務(wù)器是否運作正常。
提醒(Notification):當被監(jiān)控的某個 Redis 服務(wù)器出現(xiàn)問題時, Sentinel 可以通過 API 向管理員或者其他應(yīng)用程序發(fā)送通知。
自動故障遷移(Automatic failover):當一個主服務(wù)器不能正常工作時, Sentinel 會開始一次自動故障遷移操作, 它會將失效主服務(wù)器的其中一個從服務(wù)器升級為新的主服務(wù)器, 并讓失效主服務(wù)器的其他從服務(wù)器改為復(fù)制新的主服務(wù)器;當客戶端試圖連接失效的主服務(wù)器時, 集群也會向客戶端返回新主服務(wù)器的地址, 使得集群可以使用新主服務(wù)器代替失效服務(wù)器。
Redis Sentinel 重點總結(jié)
Sentinel 只是一個運行在特殊模式下的 Redis 服務(wù)器,因此初始化服務(wù)器時將普通 Redis 服務(wù)器使用的代碼替換成 Sentinel 專門代碼,它使用了和普通模式不同的命令表,所以 Sentinel 模式能夠使用的命令和普通 Redis 服務(wù)器能夠使用的命令不同。
Sentinel 會讀入用戶指定的配置文件,為每個要被監(jiān)視的主服務(wù)器創(chuàng)建相應(yīng)的實例結(jié)構(gòu),并創(chuàng)建連向主服務(wù)器的命令連接和訂閱連接,其中命令連接用于向主服務(wù)器發(fā)送命令請求,而訂閱連接則用于接收指定頻道的消息。
Sentinel 通過主服務(wù)器發(fā)送 INFO 命令來獲得主服務(wù)器屬下所有從服務(wù)器的地址信息,并為這些從服務(wù)器創(chuàng)建相應(yīng)的實例結(jié)構(gòu),以及連向這些從服務(wù)器的命令連接和訂閱連接。在一般情況下,Sentinel 以每十秒一次的頻率向被監(jiān)視的主服務(wù)器和從服務(wù)器發(fā)送 INFO 命令,當主服務(wù)器處于下線狀態(tài),或者 Sentinel 正在對主服務(wù)器進行故障轉(zhuǎn)移操作時,Sentinel 向從服務(wù)器發(fā)送 INFO 命令的頻率會改為每秒一次。
對于監(jiān)視同一個主服務(wù)器和從服務(wù)器的多個 Sentinel 來說,它們會以每兩秒一次的頻率,通過向被監(jiān)視服務(wù)器的 _sentinel_:hello 頻道發(fā)送消息來向其他 Sentinel 宣告自己的存在。每個 Sentinel 也會從 _sentinel_:hello 頻道中接收其他 Sentinel 發(fā)來的消息,并根據(jù)這些消息為其他 Sentinel 創(chuàng)建相應(yīng)的實例結(jié)構(gòu)以及命令連接。Sentinel 只會與主服務(wù)器和從服務(wù)器創(chuàng)建命令連接和訂閱連接,Sentinel 與 Sentinel 之間則只創(chuàng)建命令連接。
Sentinel 以每秒一次的頻率向?qū)嵗òㄖ鞣?wù)器、從服務(wù)器、其他 Sentinel)發(fā)送 PING 命令,并根據(jù)實例對 PING 命令的回復(fù)來判斷實例是否在線,當一個實例在指定的時長中連續(xù)向 Sentinel 發(fā)送無效回復(fù)時,Sentinel 會將這個實例判斷為主觀下線。
當 Sentinel 將一個主服務(wù)器判斷為主觀下線時,它會向同樣監(jiān)視這個主服務(wù)器的其它 Sentinel 進行詢問,看它們是否同意這個主服務(wù)器已經(jīng)進入主觀下線狀態(tài)。當 Sentinel 收集到足夠多的的主觀下線投票之后,它會將主服務(wù)器判斷為客觀下線,并發(fā)起一次針對主服務(wù)器的故障轉(zhuǎn)移操作。
當一個主服務(wù)器被判斷為客觀下線時,監(jiān)視這個下線主服務(wù)器的各個 Sentinel 會進行協(xié)商,選舉出一個領(lǐng)頭 Sentinel[1],并由領(lǐng)頭 Sentinel 對下線主服務(wù)器進行故障轉(zhuǎn)移操作。
Redis Sentinel 搭建
Redis Sentinel 部署技巧及其環(huán)境
一個健壯的部署至少需要三個哨兵實例,并且使用奇數(shù)個 Sentinel。
三個哨兵實例應(yīng)該放置在客戶使用獨立方式確認故障的計算機或虛擬機中,例如不同的物理機或不同可用區(qū)域的虛擬機。
哨兵配置文件中只需要配置主從復(fù)制中的主副本 ip 和端口即可,當主從進行切換時哨兵會自動修改哨兵配置文件中的主副本 ip 為新在主副本 ip。

由于本人沒有這么多服務(wù)器,因此在一臺機器上模擬一個 Redis Sentinel 集群。
| 角色 | IP 地址 | 端口號 |
|---|---|---|
| Redis Master | 127.0.0.1 | 6380 |
| Redis Slave-01 | 127.0.0.1 | 6381 |
| Redis Slave-02 | 127.0.0.1 | 6382 |
| Redis Slave-03 | 127.0.0.1 | 6383 |
| Redis Sentinel-01 | 127.0.0.1 | 26381 |
| Redis Sentinel-02 | 127.0.0.1 | 26382 |
| Redis Sentinel-03 | 127.0.0.1 | 26383 |
Redis Sentinel 安裝指南
1、下載 Redis 服務(wù)軟件包到服務(wù)器,解壓后并編譯安裝。
[root@VM_24_98_centos ~]# mkdir /usr/local/redis
[root@VM_24_98_centos ~]# wget http://download.redis.io/releases/redis-5.0.6.tar.gz
[root@VM_24_98_centos ~]# tar -zvxf redis-5.0.6.tar.gz -C /usr/local/redis
[root@VM_24_98_centos ~]# cd /usr/local/redis/redis-5.0.6/
[root@VM_24_98_centos redis-5.0.6]# make PREFIX=/usr/local/redis install
2、設(shè)置 Redis 主服務(wù)器
a. 創(chuàng)建目錄以及復(fù)制配置文件
[root@VM_24_98_centos redis]# mkdir -p /usr/local/redis/redis-master/redis-6380
[root@VM_24_98_centos redis-master]# cp -r /usr/local/redis/redis-5.0.6/redis.conf /usr/local/redis/redis-master/redis-6380/
[root@VM_24_98_centos redis-master]# vim /usr/local/redis/redis-master/redis-6380/redis.conf
b. 設(shè)置 Redis Master 主服務(wù)器配置環(huán)境
# 開啟遠程連接
bind 0.0.0.0
# 端口號
port 6380
# 守護進程
daemonize yes
# 進程文件
pidfile /usr/local/redis/redis-master/redis-6380/redis.pid
# 日志文件
logfile /usr/local/redis/redis-master/redis-6380/redis.log
# 工作目錄
dir /usr/local/redis/redis-master/redis-6380/
# 主服務(wù)器密碼
masterauth foobared
# 認證密碼
requirepass foobared
# 開啟 AOF 持久化
appendonly yes
# 每秒調(diào)用一次 fsync
appendfsync everysec
c. 啟動 Redis Master 主服務(wù)器
[root@VM_24_98_centos redis-6380]# /usr/local/redis/bin/redis-server /usr/local/redis/redis-master/redis-6380/redis.conf
[root@VM_24_98_centos redis-6380]# ps -ef |grep redis
d. 客戶端測試連接
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-server /usr/local/redis/redis-master/redis-6380/redis.conf
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6380 -a foobared
127.0.0.1:6380> INFO REPLICATION
# Replication
role:master
connected_slaves:0
master_replid:5c1034ac4dec31d6a4ae883e1eaacca3a78bc3b6
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
3、設(shè)置 Redis 從服務(wù)器
a. 創(chuàng)建目錄以及復(fù)制配置文件
[root@VM_24_98_centos redis]# mkdir -p /usr/local/redis/redis-slave/redis-6381
[root@VM_24_98_centos redis-slave]# cp -r /usr/local/redis/redis-5.0.6/redis.conf /usr/local/redis/redis-slave/redis-6381/
[root@VM_24_98_centos redis-slave]# vim /usr/local/redis/redis-slave/redis-6381/redis.conf
b. 設(shè)置 Redis Slave 從服務(wù)器配置環(huán)境
# 開啟遠程連接
bind 0.0.0.0
# 端口號
port 6381
# 守護進程
daemonize yes
# 進程文件
pidfile /usr/local/redis/redis-slave/redis-6381/redis.pid
# 日志文件
logfile /usr/local/redis/redis-slave/redis-6381/redis.log
# 工作目錄
dir /usr/local/redis/redis-slave/redis-6381/
# 主從復(fù)制 Master 節(jié)點地址 + 端口
replicaof 127.0.0.1 6380
# 主服務(wù)器密碼
masterauth foobared
# 認證密碼
requirepass foobared
# 開啟 AOF 持久化
appendonly yes
# 每秒調(diào)用一次 fsync
appendfsync everysec
c. 啟動 Redis Slave 從服務(wù)器
[root@VM_24_98_centos redis-6381]# /usr/local/redis/bin/redis-server /usr/local/redis/redis-slave/redis-6381/redis.conf
[root@VM_24_98_centos redis-6381]# ps -ef |grep redis
d. 客戶端測試連接
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-server /usr/local/redis/redis-slave/redis-6381/redis.conf
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6381 -a foobared
127.0.0.1:6381> INFO REPLICATION
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
master_last_io_seconds_ago:5
master_sync_in_progress:0
slave_repl_offset:14
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:8ecb8d89dba51e54aabb1c7feeda42fe6e6a8dc0
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14
e. 同理,從服務(wù)器 redis-6382、redis-6383 按照上面的步驟部署。
4、Redis Sentinel 部署
a. 創(chuàng)建目錄以及復(fù)制配置文件
[root@VM_24_98_centos redis]# mkdir -p /usr/local/redis/redis-sentinel/redis-26381
[root@VM_24_98_centos redis-sentinel]# cp -r /usr/local/redis/redis-5.0.6/sentinel.conf /usr/local/redis/redis-sentinel/redis-26381/
[root@VM_24_98_centos redis-sentinel]# vim /usr/local/redis/redis-sentinel/redis-26381/sentinel.conf
b. 設(shè)置 Redis Sentinel 哨兵服務(wù)器配置環(huán)境
# 端口號
port 26381
# 守護進程
daemonize yes
# 進程文件
pidfile /usr/local/redis/redis-sentinel/redis-26381/redis.pid
# 日志文件
logfile /usr/local/redis/redis-sentinel/redis-26381/redis.log
# 工作目錄
dir /usr/local/redis/redis-sentinel/redis-26381/
# 指定監(jiān)控 master{2 表示多少個 sentinel 同意}
sentinel monitor mymaster 127.0.0.1 6380 2
# 安全信息
sentinel auth-pass mymaster foobared
c. 啟動 Redis Sentinel 哨兵服務(wù)器
[root@VM_24_98_centos redis-26381]# /usr/local/redis/bin/redis-sentinel /usr/local/redis/redis-sentinel/redis-26381/sentinel.conf
[root@VM_24_98_centos redis-26381]# ps -ef |grep redis
d. 客戶端測試連接
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 26381
127.0.0.1:26381> INFO SENTINEL
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6380,slaves=3,sentinels=1
e. 同理,哨兵服務(wù)器 redis-26382、redis-26383 按照上面的步驟部署
f. 查看 Redis Master 主服務(wù)器連接狀況
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6380 -a foobared
127.0.0.1:6380> INFO REPLICATION
# Replication
role:master
connected_slaves:3
slave0:ip=127.0.0.1,port=6383,state=online,offset=20836,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=20836,lag=0
slave2:ip=127.0.0.1,port=6382,state=online,offset=20836,lag=0
master_replid:cc8ef3fe2e51a714f5b73b2fbe3bd697cacbc453
master_replid2:8ecb8d89dba51e54aabb1c7feeda42fe6e6a8dc0
master_repl_offset:20836
second_repl_offset:1522
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:20836
Redis Sentinel 場景測試
模擬場景:Redis Master 節(jié)點掛掉,查看 Redis 集群狀態(tài)。
Step1、關(guān)掉 Master 節(jié)點
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6380 -a foobared
127.0.0.1:6380> SHUTDOWN
Step2、通過哨兵查看集群狀態(tài)
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 26381
127.0.0.1:26381> INFO SENTINEL
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6381,slaves=3,sentinels=3
通過 Sentinel 信息可以看到,Master 節(jié)點已經(jīng)自動切換到 6381 端口了,說明主節(jié)點掛掉后,6381 Slave 節(jié)點自動升級成為了 Master 節(jié)點。
通過 Sentinel 日志文件顯示了 failover 的過程:

Step3、啟動 6380 Redis 服務(wù),然后查看節(jié)點角色,此時 6380 變成了 Slave,6381 為 Master 節(jié)點
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-server /usr/local/redis/redis-master/redis-6380/redis.conf
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6380 -a foobared
127.0.0.1:6380> INFO REPLICATION
# Replication
role:slave
master_host:127.0.0.1
master_port:6381
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:782228
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:84aa69ee0b191bba31162c26c4ddb1c87a705f7e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:782228
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:777789
repl_backlog_histlen:4440
Redis HA 實踐(Redis Cluster)
Redis Cluster 概述
Redis 集群是 Redis 提供的分布式數(shù)據(jù)庫方案,集群通過分片(sharding)而非一致性哈希(consistency hashing)來進行數(shù)據(jù)分享,并提供復(fù)制和故障轉(zhuǎn)移功能。Redis Cluster,主要是針對海量數(shù)據(jù) + 高并發(fā) + 高可用的場景。Redis Cluster 支撐 N 個 Redis Master Node,每個 Master Node 都可以掛載多個 Slave Node。Redis Cluster 節(jié)點間采用 Gossip 協(xié)議[2]進行通信。
節(jié)點:一個 Redis 集群通常由多個節(jié)點(node)組成,連接各個節(jié)點的工作可以使用 CLUSTER MEET <ip> <port> 命令來完成,將各個獨立的節(jié)點連接起來,構(gòu)成一個包含多個節(jié)點的集群。向一個節(jié)點 node 發(fā)送 CLUSTER MEET 命令,可以讓 node 節(jié)點與 ip 和 port 所指定的節(jié)點進行握手(handshake),當握手成功時,node 節(jié)點就會將 ip 和 port 所指定的節(jié)點添加到 node 節(jié)點當前所在的集群中。
槽指派:Redis 集群通過分片的方式來保存數(shù)據(jù)庫中的鍵值對,集群的整數(shù)據(jù)庫被分為 16384 個槽(slot),數(shù)據(jù)庫中的每個鍵都屬于這 16384 個槽的其中一個,集群中的每個節(jié)點可以處理 0 個或最多 16384 個槽。Redis 集群有固定的 16384 個 hash slot,對每個 key 計算 CRC16 值,然后對 16384 取模,可以獲取 key 對應(yīng)的 hash slot。當數(shù)據(jù)庫中的 16384 個槽都有節(jié)點在處理時,集群處于上線狀態(tài)(ok);相反地,如果數(shù)據(jù)庫中任何一個槽沒有得到處理,那么集群處于下線狀態(tài)(fail)。

Redis Cluster 重點總結(jié)
節(jié)點通過握手來將其他節(jié)點添加到自己所處的集群當中。
集群中的 16384(2的14次方)個槽可以分別指派給集群中的各個節(jié)點,每個節(jié)點都會記錄哪些槽指派給了自己,而哪些槽又被指派給其他節(jié)點。
節(jié)點在接到一個命令請求時,會先檢查這個命令請求要處理的鍵所在的槽是否由自己負責(zé),如果不是的話,節(jié)點將向客戶端返回一個 MOVED 錯誤,MOVED 錯誤攜帶的信息可以指引客戶端轉(zhuǎn)向至正在負責(zé)相關(guān)槽的節(jié)點。
對 Redis 集群的重新分片工作是由 redis-trib 負責(zé)執(zhí)行的,重新分片的關(guān)鍵是將屬于某個槽的所有鍵值對從一個節(jié)點轉(zhuǎn)移至另外一個節(jié)點。重新分片操作可以在線(online)進行,在重新分片的過程中,集群不需要下線,并且源節(jié)點和目標節(jié)點都可以繼續(xù)處理命令請求。
如果節(jié)點 A 正在遷移槽 i 至節(jié)點 B,那么當節(jié)點 A 沒能在自己的數(shù)據(jù)庫中找到命令指定的數(shù)據(jù)庫鍵時,節(jié)點 A 會向客戶端返回一個 ASK 錯誤,指引客戶端到節(jié)點 B 繼續(xù)查找指定的數(shù)據(jù)庫鍵。
MOVED 錯誤表示槽的負責(zé)權(quán)已經(jīng)從一個節(jié)點轉(zhuǎn)移到了另外一個節(jié)點,而 ASK 錯誤只是兩個節(jié)點在遷移槽的過程中使用的一種臨時措施。
Redis 集群中的節(jié)點分為主節(jié)點(master)和從節(jié)點(slave),其中主節(jié)點用于處理槽,而從節(jié)點用于復(fù)制主節(jié)點,并在主節(jié)點下線時,代替主節(jié)點繼續(xù)處理命令請求。
集群中的節(jié)點通過發(fā)送和接收消息來進行通信,常見的消息包括 MEET、PING、PONG、PUBLISH、FAIL 五種。
Redis Cluster 與 Redis Sentinel 區(qū)別
哨兵模式監(jiān)控權(quán)交給了哨兵系統(tǒng),集群模式中是工作節(jié)點自己做監(jiān)控。
哨兵模式發(fā)起選舉是選舉一個 leader 哨兵節(jié)點來處理故障轉(zhuǎn)移,集群模式是在從節(jié)點中選舉一個新的主節(jié)點,來處理故障的轉(zhuǎn)移。
Redis Cluster 搭建
Redis Cluster 部署技巧及其環(huán)境
Redis 集群至少需要 3 個節(jié)點,因為投票容錯機制要求超過半數(shù)節(jié)點認為某個節(jié)點掛了該節(jié)點才是掛了,所以 2 個節(jié)點無法構(gòu)成集群。
要保證集群的高可用,需要每個節(jié)點都有從節(jié)點,也就是備份節(jié)點,即三主三從,所以 Redis 集群至少需要 6 臺服務(wù)器。
Redis 5.0 開始不再使用 Ruby 搭建集群,而是直接使用客戶端命令 redis-cli 來創(chuàng)建。
不支持多數(shù)據(jù)庫空間,集群模式下只能使用 db0 空間。

由于資源有限,因此在一臺機器上模擬一個 Redis Cluster。
| 角色 | IP 地址 | 端口號 |
|---|---|---|
| Redis Cluster-Master-01-6391 | 127.0.0.1 | 6391 |
| Redis Cluster-Master-02-6393 | 127.0.0.1 | 6393 |
| Redis Cluster-Master-02-6395 | 127.0.0.1 | 6395 |
| Redis Cluster-Slave-01-6394 | 127.0.0.1 | 6394 |
| Redis Cluster-Slave-02-6396 | 127.0.0.1 | 6396 |
| Redis Cluster-Slave-03-6392 | 127.0.0.1 | 6392 |
Redis Cluster 安裝指南
1、下載 Redis 服務(wù)軟件包到服務(wù)器,解壓后并編譯安裝。
[root@VM_24_98_centos ~]# mkdir /usr/local/redis
[root@VM_24_98_centos ~]# wget http://download.redis.io/releases/redis-5.0.6.tar.gz
[root@VM_24_98_centos ~]# tar -zvxf redis-5.0.6.tar.gz -C /usr/local/redis
[root@VM_24_98_centos ~]# cd /usr/local/redis/redis-5.0.6/
[root@VM_24_98_centos redis-5.0.6]# make PREFIX=/usr/local/redis install
2、設(shè)置 Redis Cluster 服務(wù)器
a. 創(chuàng)建目錄以及復(fù)制配置文件
[root@VM_24_98_centos ~]# mkdir -p /usr/local/redis/redis-cluster/redis-6391
[root@VM_24_98_centos ~]# cp -r /usr/local/redis/redis-5.0.6/redis.conf /usr/local/redis/redis-cluster/redis-6391/
[root@VM_24_98_centos ~]# vim /usr/local/redis/redis-cluster/redis-6391/redis.conf
b. 設(shè)置 Redis Cluster 服務(wù)器配置環(huán)境
# 開啟遠程連接
bind 0.0.0.0
#
protected-mode no
# 端口號
port 6391
# 守護進程
daemonize yes
# 進程文件
pidfile /usr/local/redis/redis-cluster/redis-6391/redis.pid
# 日志文件
logfile /usr/local/redis/redis-cluster/redis-6391/redis.log
# 工作目錄
dir /usr/local/redis/redis-cluster/redis-6391/
# 主服務(wù)器密碼
masterauth foobared
# 認證密碼
requirepass foobared
# 開啟 AOF 持久化
appendonly yes
# 每秒調(diào)用一次 fsync
appendfsync everysec
# 開啟集群
cluster-enabled yes
# 集群的配置文件,首次啟動會自動創(chuàng)建
cluster-config-file nodes.conf
# 集群節(jié)點連接超時時間,15秒
cluster-node-timeout 15000
c. 啟動 Redis Cluster 服務(wù)器
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-server /usr/local/redis/redis-cluster/redis-6391/redis.conf
[root@VM_24_98_centos ~]# ps -ef |grep redis
d. 客戶端測試連接
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-server /usr/local/redis/redis-cluster/redis-6391/redis.conf
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6391 -a foobared
127.0.0.1:6391> CLUSTER INFO
cluster_state:fail
cluster_slots_assigned:0
cluster_slots_ok:0
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:1
cluster_size:0
cluster_current_epoch:0
cluster_my_epoch:0
cluster_stats_messages_sent:0
cluster_stats_messages_received:0
e. 同理,集群服務(wù)器 redis-6392、redis-6393 、redis-6394、redis-6395、redis-6396 按照上面的步驟部署
3、Redis 5.0 開始不再使用 ruby 搭建集群,而是直接使用客戶端命令 redis-cli 來創(chuàng)建。
a. 創(chuàng)建順序三主三從,前面三個是主后面三個是從。由于我們設(shè)置了redis集群的密碼,所以要帶上密碼。
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli --cluster create 127.0.0.1:6391 127.0.0.1:6393 127.0.0.1:6395 127.0.0.1:6392 127.0.0.1:6394 127.0.0.1:6396 --cluster-replicas 1 -a foobared

b. 客戶端測試連接
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6391 -a foobared
127.0.0.1:6391> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:1153
cluster_stats_messages_pong_sent:1241
cluster_stats_messages_sent:2394
cluster_stats_messages_ping_received:1236
cluster_stats_messages_pong_received:1153
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:2394
127.0.0.1:6391> CLUSTER NODES
cdfd726c3c35586770412cade1fe5c56d4285b0e 127.0.0.1:6394@16394 slave c54ebef126b30b5bd9cb157ccc0b6ddb952a1f50 0 1574234724000 5 connected
c8daea9291a5cfdf0b3e032bc3a80d7e3cbc75cc 127.0.0.1:6393@16393 master - 0 1574234725711 2 connected 5461-10922
43c325955c74f0ed79de6850dca8a509195acb13 127.0.0.1:6392@16392 slave 718f66ab8b3574597a97b90f8257773d0483c556 0 1574234724000 4 connected
3a32043079bf6af3723230ee3e6412e84dd66180 127.0.0.1:6396@16396 slave c8daea9291a5cfdf0b3e032bc3a80d7e3cbc75cc 0 1574234724708 6 connected
c54ebef126b30b5bd9cb157ccc0b6ddb952a1f50 127.0.0.1:6391@16391 myself,master - 0 1574234725000 1 connected 0-5460
718f66ab8b3574597a97b90f8257773d0483c556 127.0.0.1:6395@16395 master - 0 1574234723000 3 connected 10923-16383
Redis Cluster 場景測試
(1)模擬場景:Redis Cluster 中 某個 Master 節(jié)點掛掉,查看 Redis Cluster 狀態(tài)。
Step1、關(guān)掉 Cluster-Master-6391 節(jié)點
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6391 -a foobared
127.0.0.1:6391> SHUTDOWN
Step2、查看集群狀態(tài)
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6393 -a foobared
127.0.0.1:6393> CLUSTER NODES
43c325955c74f0ed79de6850dca8a509195acb13 127.0.0.1:6392@16392 slave 718f66ab8b3574597a97b90f8257773d0483c556 0 1574236204772 4 connected
3a32043079bf6af3723230ee3e6412e84dd66180 127.0.0.1:6396@16396 slave c8daea9291a5cfdf0b3e032bc3a80d7e3cbc75cc 0 1574236206778 6 connected
cdfd726c3c35586770412cade1fe5c56d4285b0e 127.0.0.1:6394@16394 master - 0 1574236201000 7 connected 0-5460
718f66ab8b3574597a97b90f8257773d0483c556 127.0.0.1:6395@16395 master - 0 1574236206000 3 connected 10923-16383
c54ebef126b30b5bd9cb157ccc0b6ddb952a1f50 127.0.0.1:6391@16391 master,fail - 1574236049092 1574236047289 1 disconnected
c8daea9291a5cfdf0b3e032bc3a80d7e3cbc75cc 127.0.0.1:6393@16393 myself,master - 0 1574236204000 2 connected 5461-10922
通過 CLUSTER NODES 信息可以看到,Cluster-Master-01-6391 主節(jié)點處于下線狀態(tài)(fail),其 Cluster-Master-01-6391 節(jié)點的從節(jié)點 Cluster-Slave-01-6394 變?yōu)橹鞴?jié)點;說明主節(jié)點掛掉后,6394 Slave 節(jié)點自動升級成為了 Master 節(jié)點。
Step3、啟動 6391 Redis 服務(wù),然后查看節(jié)點角色,此時 6391 變成了 Slave,6394 為 Master 節(jié)點
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-server /usr/local/redis/redis-cluster/redis-6391/redis.conf
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6391 -a foobared
127.0.0.1:6391> CLUSTER NODES
43c325955c74f0ed79de6850dca8a509195acb13 127.0.0.1:6392@16392 slave 718f66ab8b3574597a97b90f8257773d0483c556 0 1574238264397 4 connected
c54ebef126b30b5bd9cb157ccc0b6ddb952a1f50 127.0.0.1:6391@16391 myself,slave cdfd726c3c35586770412cade1fe5c56d4285b0e 0 1574238261000 1 connected
3a32043079bf6af3723230ee3e6412e84dd66180 127.0.0.1:6396@16396 slave c8daea9291a5cfdf0b3e032bc3a80d7e3cbc75cc 0 1574238265400 6 connected
c8daea9291a5cfdf0b3e032bc3a80d7e3cbc75cc 127.0.0.1:6393@16393 master - 0 1574238263000 2 connected 5461-10922
718f66ab8b3574597a97b90f8257773d0483c556 127.0.0.1:6395@16395 master - 0 1574238263000 3 connected 10923-16383
cdfd726c3c35586770412cade1fe5c56d4285b0e 127.0.0.1:6394@16394 master - 0 1574238264000 7 connected 0-5460
(2)模擬場景:為 Redis Cluster 添加一個新主(master)節(jié)點
Step1、按照上面的步驟新增一 Redis Cluster 服務(wù)器 Cluster-Master-04-6397
Step2、將 Cluster-Master-04-6397 節(jié)點加入 Redis Cluster 中(127.0.0.1:6391 為集群中任意可用的節(jié)點)
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli --cluster add-node 127.0.0.1:6397 127.0.0.1:6391 -a foobared

Step3、為節(jié)點 Cluster-Master-04-6397 分配 slots(127.0.0.1:6391 為集群中任意可用的節(jié)點)
[root@VM_24_98_centos redis-cluster]# /usr/local/redis/bin/redis-cli --cluster reshard 127.0.0.1:6391 -a foobared

(3)模擬場景:為 Redis Cluster 某個 Master 節(jié)點添加 一個新從(slave)節(jié)點
Step1、按照上面的步驟新增一 Redis Cluster 服務(wù)器 Cluster-Slave-04-6398
Step2、將 Cluster-Slave-04-6398 節(jié)點加入 Redis Cluster 中(127.0.0.1:6391 為集群中任意可用的節(jié)點)
// 這種方法隨機為 6398 指定一個 master
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli --cluster add-node 127.0.0.1:6398 127.0.0.1:6391 --cluster-slave -a foobared
// 這種方式將為 6398 指定某個 master-id
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli --cluster add-node 127.0.0.1:6398 127.0.0.1:6391 --cluster-slave --cluster-master-id 5cf471cf39f0104f69d06c80d0dfdcc8aaa96b7c -a foobared
Step3、查看集群狀態(tài)
[root@VM_24_98_centos ~]# /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6391 -a foobared
127.0.0.1:6391> CLUSTER NODES
5cf471cf39f0104f69d06c80d0dfdcc8aaa96b7c 127.0.0.1:6397@16397 master - 0 1574243297701 7 connected 0-1364 5461-6826 10923-12287
207628f6fb8b3bb9a22db757507350fb880d4990 127.0.0.1:6396@16396 slave 94af5d349465be57400b6a4a1d770d56ad3d94ce 0 1574243294000 6 connected
94af5d349465be57400b6a4a1d770d56ad3d94ce 127.0.0.1:6393@16393 master - 0 1574243296700 2 connected 6827-10922
2e0134b0a87a73903d4774b6b37dd43e78e93733 127.0.0.1:6391@16391 myself,master - 0 1574243292000 1 connected 1365-5460
21a288afc7b6addebcd943ca606dd34f6b9c99db 127.0.0.1:6398@16398 slave 5cf471cf39f0104f69d06c80d0dfdcc8aaa96b7c 0 1574243295697 7 connected
63bc9da88066b475bd878a56a11dd18023b211b6 127.0.0.1:6394@16394 slave 2e0134b0a87a73903d4774b6b37dd43e78e93733 0 1574243295000 5 connected
c3d20b7f2df806ec87f3d45a7e334b5a2d3abe5b 127.0.0.1:6395@16395 master - 0 1574243296000 3 connected 12288-16383
f6a7c788d9e5d40bc62a3723ba02c25607cc2825 127.0.0.1:6392@16392 slave c3d20b7f2df806ec87f3d45a7e334b5a2d3abe5b 0 1574243293694 4 connected
參考博文
[1]. 一文搞懂 Raft 算法
[2]. Redis 哨兵模式實現(xiàn)主從故障互切換
[3]. Redis cluster tutorial
[4]. redis cluster 的Gossip協(xié)議介紹
注腳
[1]. 領(lǐng)頭 Sentinel:Sentinel 系統(tǒng)選舉領(lǐng)頭 Sentinel 的方式是對 Raft 算法的領(lǐng)頭選舉方法的實現(xiàn),Raft 算法是一個共識算法,是工程上使用較為廣泛的強一致性、去中心化、高可用的分布式協(xié)議。
[2]. Gossip 協(xié)議:Gossip protocol 也叫 Epidemic Protocol(流行病協(xié)議),實際上它還有很多別名,比如:“流言算法”、“疫情傳播算法” 等。Gossip 過程是由種子節(jié)點發(fā)起,當一個種子節(jié)點有狀態(tài)需要更新到網(wǎng)絡(luò)中的其他節(jié)點時,它會隨機的選擇周圍幾個節(jié)點散播消息,收到消息的節(jié)點也會重復(fù)該過程,直至最終網(wǎng)絡(luò)中所有的節(jié)點都收到了消息。這個過程可能需要一定的時間,由于不能保證某個時刻所有節(jié)點都收到消息,但是理論上最終所有節(jié)點都會收到消息,因此它是一個“最終一致性協(xié)議”
source:https://morning-pro.github.io/archives/d63e1e23.html推薦閱讀
國產(chǎn)小眾瀏覽器因屏蔽視頻廣告,被索賠100萬(后續(xù))
年輕人“不講武德”:因看黃片上癮,把網(wǎng)站和786名女主播起訴了
關(guān)于程序員大白
程序員大白是一群哈工大,東北大學(xué),西湖大學(xué)和上海交通大學(xué)的碩士博士運營維護的號,大家樂于分享高質(zhì)量文章,喜歡總結(jié)知識,歡迎關(guān)注[程序員大白],大家一起學(xué)習(xí)進步!

