Redis實戰總結-Redis的高可用性
在之前的部落格《Redis實戰總結-配置、持久化、複製》給出了一種Redis主從複製機制,簡單地實現了Redis高可用。然後,如果Master伺服器宕機,會導致整個Redis癱瘓,這種方式的高可用性較低。正常會採用多臺Redis伺服器構成一個叢集,即使某臺,或者某幾臺Redis宕機,Redis叢集仍能正常執行,從而提高其高可用性。
在Redis中,主要存在兩種方式實現Redis叢集機制:
Redis Sentinel叢集機制:在Redis2.X版本,往往都是通過這種方式實現Redis的高可用。redis-sentinel是在master-slave機制上加入監控機制哨兵Sentinel實現的。
Redis Cluster叢集機制:在Redis3.0版本後推出了redis-cluster叢集機制。redis-cluster叢集中各個節點之間是對等的,即master-master模式。
**注意:**Redis Sentinel叢集是解決HA問題的(主從同步),Redis Cluster叢集是解決sharding問題的(分割槽),兩種不重複,可以混合使用。
下面詳解這兩種叢集,並給出具體的演示示例。
1. Redis Sentinel叢集機制
Redis-Sentinel是在master-slave機制上加入監控機制哨兵Sentinel實現的。Sentinel主要功能就是為Redis Master-Slave叢集提供:
- 監控(Monitoring): Sentinel 會不斷地檢查你的主伺服器和從伺服器是否運作正常。
- 提醒(Notification): 當被監控的某個 Redis 伺服器出現問題時, Sentinel 可以通過 API 向管理員或者其他應用程式傳送通知。
- 自動故障遷移(Automatic failover): 當一個主伺服器不能正常工作時, Sentinel 會開始一次自動故障遷移操作, 它會將失效主伺服器的其中一個從伺服器升級為新的主伺服器, 並讓失效主伺服器的其他從伺服器改為複製新的主伺服器; 當客戶端試圖連線失效的主伺服器時, 叢集也會向客戶端返回新主伺服器的地址, 使得叢集可以使用新主伺服器代替失效伺服器。
在Sentinel叢集中,一個最小的Master-Slave單元包含一個master和一個slave伺服器。當master失效後,sentinel自動將slave提升為master,從而可以減少管理員的人工切換slave的操作過程。
1.1 Redis-Sentinel叢集架構圖
1.2 各個機器配置
部署在本地機器上,保證各個埠號不一樣,具體配置如下
Redis伺服器:
- master:127.0.0.1:6379
- slave01:127.0.0.1:6389
- slave02:127.0.0.1:6399
Sentinel伺服器
- sentinel01:127.0.0.1:26379
- sentinel02:127.0.0.1:26389
- sentinel03:127.0.0.1:26399
1.3 redis.conf和sentinel.conf配置
redis.conf
- master特殊配置如下:
# 後臺執行緒啟動 daemonize yes # 監聽埠號 port 6379 # 訪問驗證密碼 requirepass "123456"
- slave特殊配置如下:
# 後臺執行緒啟動 daemonize yes # 監聽埠號,如果為slave02,埠號為6399 port 6389 # 主節點訪問密碼 masterauth "123456" # 訪問驗證密碼 requirepass "123456" # 主節點伺服器IP和埠號 slaveof 127.0.0.1 6379
sentinel.conf
# 後臺執行緒啟動
daemonize yes
# 監聽埠號,如果為sentinel02,則埠號為26389,如果為sentinel01,則埠號為26399
port 26379
#1表示在sentinel叢集中只要有兩個節點檢測到redis主節點出故障就進行切換
sentinel monitor mymaster 127.0.0.1 6379 1
# master節點密碼驗證
sentinel auth-pass mymaster 123456
#如果3秒內mymaster無響應,則認為mymaster宕機了
sentinel down-after-milliseconds mymaster 3000
# 選項指定了在執行故障轉移時, 最多可以有多少個從伺服器同時對新的主伺服器進行同步, 這個數字越小, 完成故障轉移所需的時間就越長
sentinel parallel-syncs mymaster 1
#如果10秒後,mysater仍沒活過來,則啟動failover
sentinel failover-timeout mymaster 10000
注意:
- 1.如果上述涉及的所有配置均放置在同一目錄下,需保證各配置名稱不同;
- 2.在配置中,不同例項的日誌輸出、快照檔案要求名稱不能一樣,具體可自行配置;
- 3.一定要保證”sentinel myid”不相同,否則無法進行故障轉移
1.4 啟動叢集及啟動後結果詳情展示
各Redis節點啟動:
redis-server redis_****.conf
各Sentinel節點啟動
redis-sentinel sentinel_*****.conf
- Redis Master節點詳情展示
- Redis Slave節點效果截圖展示
- 各個Sentinel節點詳情展示
1.5 高可用性場景測試
- Master宕機
sentinel使用failover機制重新選舉出master - Master恢復
master節點恢復後,由Master變成slave - Slave宕機
哨兵發現6399已經宕機,等待6399的恢復(主觀下線)
2. Redis Cluster叢集機制
2.1 Redis-cluster介紹
Redis-cluster是一種伺服器Sharding技術,Redis3.0以後版本正式提供支援。
Redis-cluster沒有使用一致性hash,而是引入了雜湊槽的概念。Redis-cluster中有16384個雜湊槽,每個key通過CRC16校驗後對16384取模來決定放置哪個槽。Cluster中的每個節點負責一部分hash槽(hash slot),比如叢集中存在三個節點,則可能存在的一種分配如下:
- 節點A包含0到5500號雜湊槽;
- 節點B包含5501到11000號雜湊槽;
- 節點C包含11001 到 16384號雜湊槽。
這種叢集架構很容易擴充套件,如果擴充一個節點D,只需要將A、B、C節點中的部分槽放置在D上;如果想移除節點A,只需要將A的slot轉移到B和C節點上。由於將雜湊槽從一個節點移動到另一個節點不需要停止服務,只需要通過命令直接再分配,因而上述拓展不會造成叢集不可用。目前這種方式還是一種半自動的方式,需要人工介入。
2.2 Redis-Cluster主從複製
在Redis-Cluster中,如果某個節點宕機或者處在不可用狀態時,那它負責的Hash槽也將失效,導致整個叢集不可用。因而為了提供高可用性,正常會將每個節點配置成主從式結構,即一個master節點,掛在多個slave節點。如果Master節點失效時,叢集便會選取一個slave節點作為master,繼續提供服務,從而不會導致整個叢集不可用。
2.3 Redis-Cluster叢集模擬
2.3.1 Redis-Cluster叢集準備
- 叢集部署圖
叢集由三個節點組成,每個節點均為主從式架構。因而共需要建立6個Redis例項,分配如下:
- Redis01:127.0.0.1:7000
- Redis02:127.0.0.1:7001
- Redis03:127.0.0.1:7002
- Redis04:127.0.0.1:7003
- Redis05:127.0.0.1:7004
- Redis06:127.0.0.1:7005
對於每個例項的redis_700*.conf配置如下:
# 監聽埠號 port 700* # 開啟叢集 cluster-enabled yes # 修改叢集載入配置檔案,不需要手動建立,啟動後預設生成,並且需要時自動更新 cluster-config-file /Users/guweiyu/develop/redis/redis-cluster/workpid/nodes-7000.conf # 叢集中的節點能夠失聯的最大時間,超過這個時間,該節點就會被認為故障 cluster-node-timeout 15000 # 預設為“no”,表示部分Key所在的節點不可用時,叢集仍然為可達節點提供服務;如果為“yes”,表示部分key所在的節點不可用時,則整個叢集停止服務。注意:實際使用中要修改為"yes" cluster-require-full-coverage no
安裝ruby,如果為Mac OS系統,直接執行即可:
brew install ruby
2.3.2 叢集啟動
啟動所有Redis例項,可以編寫一個啟動和停止所有redis例項的指令碼(start.sh,stop.sh)
redis-server redis_7000.conf redis-server redis_7001.conf redis-server redis_7002.conf redis-server redis_7003.conf redis-server redis_7004.conf redis-server redis_7005.conf ps -ef | grep redis-server echo "redis 7000-7005全部啟動完成"
redis-cli -p 7000 shutdown redis-cli -p 7001 shutdown redis-cli -p 7002 shutdown redis-cli -p 7003 shutdown redis-cli -p 7004 shutdown redis-cli -p 7005 shutdown ps -ef | grep redis-server echo "redis-server 7000-7005節點已全部停止"
- 建立redis-cluster
Redis中建立叢集是通過redis-trib.rb命令實現的,redis-trib.rb位於Redis原始碼的src目錄下,可將其直接拷貝到當前目錄下。
執行命令
./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
如果出現如下錯誤:
/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- redis (LoadError)
from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from ./redis-trib.rb:25:in `<main>'
這是由於沒有安裝redis的第三方介面導致的。因此需要給Ruby安裝client包,如下(必須加上sudo執行,否則會執行失敗):
sudo gem install redis
再執行建立叢集命令,結果如下:
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:7000
127.0.0.1:7001
127.0.0.1:7002
Adding replica 127.0.0.1:7004 to 127.0.0.1:7000
Adding replica 127.0.0.1:7005 to 127.0.0.1:7001
Adding replica 127.0.0.1:7003 to 127.0.0.1:7002
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: aab0162a039d2f224322afe6caf2e153230f2d82 127.0.0.1:7000
slots:0-5460 (5461 slots) master
M: 058204226f52757925a606b9697a8e39756bfdff 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
M: 857075aef280cf35cd369ebc30738cd31c05e479 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
S: 7dac141fa9510315905f505be52bba0208c391ab 127.0.0.1:7003
replicates aab0162a039d2f224322afe6caf2e153230f2d82
S: 65a2bc432e5930e97f0fd172eb838af9f07229b6 127.0.0.1:7004
replicates 058204226f52757925a606b9697a8e39756bfdff
S: 3d2a665d2e2eb28acb0a187c1a0b4bbce9ce87d2 127.0.0.1:7005
replicates 857075aef280cf35cd369ebc30738cd31c05e479
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 127.0.0.1:7000)
M: aab0162a039d2f224322afe6caf2e153230f2d82 127.0.0.1:7000
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 3d2a665d2e2eb28acb0a187c1a0b4bbce9ce87d2 127.0.0.1:7005
slots: (0 slots) slave
replicates 857075aef280cf35cd369ebc30738cd31c05e479
S: 65a2bc432e5930e97f0fd172eb838af9f07229b6 127.0.0.1:7004
slots: (0 slots) slave
replicates 058204226f52757925a606b9697a8e39756bfdff
S: 7dac141fa9510315905f505be52bba0208c391ab 127.0.0.1:7003
slots: (0 slots) slave
replicates aab0162a039d2f224322afe6caf2e153230f2d82
M: 857075aef280cf35cd369ebc30738cd31c05e479 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
M: 058204226f52757925a606b9697a8e39756bfdff 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
建立成功,16384個Hash槽分配完成,所有節點(Master和slave節點)均已加入到叢集中。三個Master節點分配的Hash槽及從節點如下:
Master01:127.0.0.1:7000
M: aab0162a039d2f224322afe6caf2e153230f2d82 slots:0-5460 (5461 slots) master 127.0.0.1:7004 to 127.0.0.1:7000
Master02:127.0.0.1:7001
M: 058204226f52757925a606b9697a8e39756bfdff slots:5461-10922 (5462 slots) master 127.0.0.1:7005 to 127.0.0.1:7001
Master03:127.0.0.1:7002
M: 857075aef280cf35cd369ebc30738cd31c05e479 slots:10923-16383 (5461 slots) master 127.0.0.1:7003 to 127.0.0.1:7002
2.3.3 叢集測試
- 測試叢集存取值
客戶端命令redis-cli連線叢集需要帶上”-c”, 比如redis-cli -c -p 埠號
127.0.0.1:7000> set test1 guweiyu
OK
127.0.0.1:7000> set name guweiyu
-> Redirected to slot [5798] located at 127.0.0.1:7001
OK
127.0.0.1:7001> get name
"guweiyu"
127.0.0.1:7001> get test1
-> Redirected to slot [4768] located at 127.0.0.1:7000
"guweiyu"
127.0.0.1:7000>
測試發現”set test1 guweiyu”,直接返回OK,說明該值就是儲存在7000上,執行“set name guweiyu”發生了Redirected到7001上,獲取的時候,同樣出現上述情況。這個是Redis Cluster去中心特性,訪問叢集中的任一節點,均可直接操作叢集。
主節點宕機測試
從節點宕機
*