REDIS哨兵模式和集群模式


1. REDIS 哨兵模式搭建

sentinel (哨兵模式):選擇一個redis實例作為sentinel ,實時監控主服務器和從服務器運行狀態,並且實現自動故障轉移,當一個主服務器不能正常工作時,Redis Sentinel 可以將一個從服務器升級為主服務器, 並對其他從服務器進行配置,讓它們使用新的主服務器,同時會通知系統管理員或其他計算機程序,要實現高可用,起碼設置3個哨兵

 

什么時候執行故障遷移?

當quorum個sentinel認為當前master 已經不可用時執行故障遷移

M代表master

S代表哨兵

R代表slave(replica)

## step1

## 按照復制的方式搭建一主二從

https://www.cnblogs.com/start-from-zero/p/12818555.html

 

 

## step2

## 簡單配置以下 sentinel.conf (在redis安裝目錄)

## sentinel monitor mymaster 127.0.0.1 6379 1 (master的ip和端口,分別為 別名,IP地址,端口號 表示有幾個sentinel同意才會執行故障轉移)

## sentinel auth-pass mymaster 12345  (如果master 設置了密碼要設置,而且每個slave 都要相同的密碼,不然無法切換,否則不用設置)

## daemonize yes

## logfile "/usr/logs/redis/redis6382.log"

## cp /usr/redis-4.0.14/sentinel.conf /usr/conf/redis/sentinel6382.conf

 

## step 3 

## redis-sentinel /usr/conf/redis/sentinel6382.conf

## 啟動成功 

 

## step 4

## tail -f /usr/conf/redis/redis6382.log

## 已經開始監聽3個實例

## 第一行表示正在監聽master服務器,只要一個哨兵認為master故障就可以執行故障遷移

 

## step5 

## 宕機測試

## netstat -lnp | grep redis

 

## kill -9 943   (kill 掉master實例)

1048:X 21 Apr 15:18:15.944 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1048:X 21 Apr 15:18:15.944 # Sentinel ID is 0b147680222c65e1292cc13c73638f6aed6cdcb1
1048:X 21 Apr 15:18:15.944 # +monitor master mymaster 127.0.0.1 6379 quorum 1
## sentinel 正在監控master
1048:X 21 Apr 15:18:15.944 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1048:X 21 Apr 15:18:15.945 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
## sentinel開始監控所有的slave
1048:X 21 Apr 15:20:00.234 # +sdown master mymaster 127.0.0.1 6379
## master 主觀宕機,當一個sentinel ping節點的時候發現沒有收到有效的回復則認為該節點下線,當只有一個sentinel的時候,一個sentinel認為下線也就是客觀下線
1048:X 21 Apr 15:20:00.234 # +odown master mymaster 127.0.0.1 6379 #quorum 1/1
## 當認為監控的某節點為客觀下線的sentinel數量達到quorum則為客觀下線,開始故障遷移
1048:X 21 Apr 15:20:00.234 # +new-epoch 1
## 當前的的版本號為1,當遇到變更時會加 1
1048:X 21 Apr 15:20:00.234 # +try-failover master mymaster 127.0.0.1 6379
## 開始故障恢復,master 已經達到下線的條件,就是主觀認為某節點主觀下線的sentinel 數量 > quorum
1048:X 21 Apr 15:20:00.235 # +vote-for-leader 0b147680222c65e1292cc13c73638f6aed6cdcb1 1
##投票開始 sentinel-0b147680222c65e1292cc13c73638f6aed6cdcb1 已投	
1048:X 21 Apr 15:20:00.235 # +elected-leader master mymaster 127.0.0.1 6379
## 選擇一個哨兵執行 failover故障遷移 ,
1048:X 21 Apr 15:20:00.235 # +failover-state-select-slave master mymaster 127.0.0.1 6379
## 從slave 中選擇一個做master
1048:X 21 Apr 15:20:00.311 # +selected-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
## 選中127.0.0.1:6381 作為新master
1048:X 21 Apr 15:20:00.311 * +failover-state-send-slaveof-noone slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
## 127.0.0.1:6381 實例上執行slaveof no one 更換新主的角色
1048:X 21 Apr 15:20:00.382 * +failover-state-wait-promotion slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
## 等待其他sentinel 確認新slave
1048:X 21 Apr 15:20:01.279 # +promoted-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
## 確認成功,新主成為master
1048:X 21 Apr 15:20:01.279 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6379
## failover 故障遷移開始更改 slave 配置
1048:X 21 Apr 15:20:01.332 * +slave-reconf-sent slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
## 發送新的slaveof命令給127.0.0.1 6380
1048:X 21 Apr 15:20:02.299 * +slave-reconf-inprog slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
## 127.0.0.1:6380 執行slaveof命令和sync命令
1048:X 21 Apr 15:20:02.299 * +slave-reconf-done slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
## 執行完成,此時查看配置文件可以看到6381的已經移除了slaveof參數,6380的配置slaveof指向了6381,而不是原來的6379
1048:X 21 Apr 15:20:02.357 # +failover-end master mymaster 127.0.0.1 6379
## 故障遷移成功
1048:X 21 Apr 15:20:02.357 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381
## 各個sentinel開始監控新的master
1048:X 21 Apr 15:20:02.358 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
## sentinel 監聽到新主的slave
1048:X 21 Apr 15:20:02.358 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381
1048:X 21 Apr 15:20:32.417 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381
## 監控中仍然有一台slave 下線中

 

## step 6

## redis-server /usr/conf/redis/redis6379.conf

## 重新啟動舊主

1048:X 21 Apr 16:07:02.505 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381
## 127.0.0.1:6379上線
1048:X 21 Apr 16:07:12.475 * +convert-to-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381
## 此時查看配置文件可以看到6379的配置slaveof指向了6381,

 

2.sentinel參數說明

port 26379

## Sentinel使用Redis instances Pub/Sub功能(基於端口實現)來發現監視相同主服務器和slave的其他Sentinel

## 哨兵與其他哨兵通過保持聯系,以便相互檢查對方的可用性,並交換消息,通過端口來實現

## 所以要保證port 26379可用 ,當然也可以更改

 

sentinel client-reconfig-script <master-name> <script-path>

## 當主服務器因故障轉移而變更時,可以調用腳本執行特定於應用程序的任務,以通知客戶端,配置已更改且主服務器地址已經變更

 

sentinel deny-scripts-reconfig

## 默認情況下,SENTINEL SET將無法在運行時更改notification-script和client-reconfig-script

## 設置為no,cli中sentinel set 可以設置任何參數

 

sentinel down-after-milliseconds <master-name> <milliseconds>

## 主節點或slave在指定時間內沒有回復PING,則認為節點下線,默認30秒

 

sentinel monitor mymaster 127.0.0.1 6381 1

## sentinel監控的主節點

 

sentinel auth-pass mymaster 12345

## 如果監控的master節點有密碼,則需要配置,否則不用設置

 

sentinel failover-timeout <master-name> <milliseconds>

## 執行failover的最長時間,默認3分鍾,

取消已經超時的故障轉移,但是前提是沒有產生任何配置更改(SLAVEOF NO ONE 還沒執行)

 

sentinel notification-script <master-name> <script-path>

## 當報警時執行的通知腳本 如SDOWN ODOWN

 

%poch%

## 變更次數

 

R raplica /slave

M master

S sentinel

測試quarum只對master 是否已經下線有作用,但是不對挑選一個sentinel 去執行故障遷移有用

10.199.203.210一個master 一個sentinel

10.199.234.92 一個slave 一個sentinel

 

test1

## step 1

## 10.199.203.210 執行:

## netstat -lnp | grep redis

 

 ## kill 1734

 ## quorum 足夠判斷 10.199.234.92已經下線,當sentinel沒被下線的時能執行failover,也就是說當sentinel間能通信的時候,就能選舉一個sentinel去執行failover故障遷移

 

test2 

## step 1

## 10.199.234.92 執行:

## netstat -lnp | grep redis

 

## kill 30746 30711

 ## quorum 足夠判斷 10.199.234.92已經下線,但不能執行failover,也就是說當sentinel間不能通信的時候,就不能選舉一個sentinel去執行failover故障遷移

 

3.搭建redis cluster

## step 1

## 修改配置文件

## vim /usr/redis4.0.14/redis.conf

## 設置 6份配置文件,3主3從

port 7000

pid /tmp/redis7000.pid

logfile "/usr/logs/redis/redis7000.log"

daemonize yes

cluster-enabled yes

cluster-config-file nodes.conf

cluster-node-timeout 5000

appendonly yes

## cp /usr/redis4.0.14/redis.conf /usr/conf/cluster/7000.conf (6份7001,7002....7005)

 

## step2 (redis3~4需要執行)

## redis-server /usr/redis/conf/cluster/7000.conf

## redis-server /usr/redis/conf/cluster/7001.conf

...............

## redis-server /usr/redis/conf/cluster/7005.conf

## netstat -lnp | grep redis

## 高位端口用於cluster 集群中節點的通信,不用於客戶端進行連接

## 低位端口用於客戶端進行連接

 

## step 4 (redis3~4需要執行)

## 安裝ruby

## yum install ruby

## 這種方式安裝的ruby版本太低,redis不能用,需要ruby2.3,所以需要rvm 來升級,太麻煩,直接安裝ruby2.5

## wget https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.3.tar.gz 

## tar zxvf ruby-2.5.3.tar.gz

## configure

## make && make install

## gem install redis

 

## step5 (redis3~4需要執行)

## gem install redis

## 因為redis3~4 需要執行 redis-trib來創建集群,而執行redis-trib需要redis gem

 

## step 6

## 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

 

 

 

 

 

## 集群開啟成功 ,把16384+ 個哈希槽分配給3個master 節點

 

## step 7  每次搭建完集群都要查看每個節點的狀態信息

## redis-cli -p 7000 -c cluster info

## redis-cli -p 7001 -c cluster info

## redis-cli -p 7002 -c cluster info

 

## 確認每個節點的集群狀態,因為加入A節點的槽部分不可用,A的cluster_state的狀態會為fail,其他節點的clutser_state會顯示ok

 

## 搭建完集群起碼要查看3個節點的集群狀態,因為沒有中心節點,所以通信靠ping和ping的數據包,容易會發生不一致狀態

 

## step 8 查看其中一個master節點的日志

4062:M 22 Apr 14:32:03.151 # configEpoch set to 1 via CLUSTER SET-CONFIG-EPOCH
4062:M 22 Apr 14:32:03.175 # IP address for this node updated to 127.0.0.1
4062:M 22 Apr 14:32:06.381 * Slave 127.0.0.1:7004 asks for synchronization
## 7004 作為該master 的從節點,申請同步數據
4062:M 22 Apr 14:32:06.382 * Partial resynchronization not accepted: Replication ID mismatch (Slave asked for '5565534942a1f5a86dbbf4c7ff89ec0b21a6d733', my replication IDs are '6ddffd1a2fd0b1fdd09c45244429bd9277e0fa5b' and '0000000000000000000000000000000000000000')
## 部分復制失敗,不存在該replid
4062:M 22 Apr 14:32:06.383 * Starting BGSAVE for SYNC with target: disk
## 開始執行全部復制
4062:M 22 Apr 14:32:06.383 * Background saving started by pid 18305
## fork了一個子進程來執行全部復制
18305:C 22 Apr 14:32:06.392 * DB saved on disk
18305:C 22 Apr 14:32:06.393 * RDB: 0 MB of memory used by copy-on-write
4062:M 22 Apr 14:32:06.481 * Background saving terminated with success
4062:M 22 Apr 14:32:06.481 * Synchronization with slave 127.0.0.1:7004 succeeded
## 同步成功
4062:M 22 Apr 14:32:08.083 # Cluster state changed: ok
## 集群狀態

## step9 

## 此時哈希槽已經分配給了3個主節點

## redis-cli -p 7000

## set nviosdnv aiosd

 

## 對鍵nviosdnv執行crc16后對應槽位不在該節點上,保存失敗

## 開啟集群后,客戶端訪問一定要加 -c 告訴server是集群模式

## redis-cli -p 7000 -c

 

4.參數說明及測試

參數
說明
cluster-enabled 集群開關
cluster-config-file

集群配置文件的名稱,每個節點都有一個集群相關的配置文件,持久化保存集群的信息

這個文件並不需要手動配置,這個配置文件有Redis生成並更新

每個Redis集群節點需要一個單獨的配置文件,請確保與實例運行的系統中配置文件名稱不沖突

cluster-node-timeout 節點互連超時的閥值。集群節點超時毫秒數
cluster-slave-validity-factor

 在進行故障轉移的時候,全部slave都會請求申請為master

但是有些slave可能與master斷開連接一段時間了,導致數據過於陳舊,這樣的slave不應該被提升為master

該參數就是用來判斷slave節點與master斷線的時間是否過長,設置為0表示不開啟

 (node-timeout * slave-validity-factor) + repl-ping-slave-period計算slave的數據是否過於陳舊

cluster-migration-barrier 那些分配后仍然剩余migration barrier個從節點的主節點才會觸發節點分配,避免有主節點沒有從節點的情況
cluster-require-full-coverage 默認情況下,集群全部的slot有節點負責,集群狀態才為ok,才能提供服務。設置為no,可以在slot沒有全部分配的時候提供服務
cluster-slave-no-failover

當設置為“是”時,此選項將阻止從屬服務器嘗試故障轉移其主機故障期間的主機

 

cluster-config-file 同時也是redis-cli -c -p 7000 cluster nodes 的輸出信息

replid                               ip:客戶端連接端口號@節點通信端口號  角色  slave的master             時間戳  時間戳      多少個節點已經連接  節點擁有哈希槽
461ce1a255c4c1726b90d95b34ec4522b0a76351 127.0.0.1:7004@17004 slave b384f758ce1c18b95dd5d5daaef71d035e21d239 0 1587537129000 5 connected
b384f758ce1c18b95dd5d5daaef71d035e21d239 127.0.0.1:7000@17000 myself,master - 0 1587537127000 1 connected 0-5460
47bef6d030f33e5586f9611c336acce9df42023e 127.0.0.1:7005@17005 slave 493910888834f05731d2f93daf0154354a09b772 0 1587537128084 6 connected
3543b386c739e6d186b887e8d2c5316478f6d7bc 127.0.0.1:7003@17003 slave 25b52321824aa5e4616faf9a0723f2365ccb2ed6 0 1587537126081 4 connected
493910888834f05731d2f93daf0154354a09b772 127.0.0.1:7001@17001 master - 0 1587537129084 2 connected 5461-10922
25b52321824aa5e4616faf9a0723f2365ccb2ed6 127.0.0.1:7002@17002 master - 1587537130085 1587537128000 3 connected 10923-16383
vars currentEpoch 6 lastVoteEpoch 0

 

 

cluster-node-timeout

## step 1

## netstat -lnp | grep redis

 

 

 ## kill -9 4100    ---kill掉7001的節點

## cluster-node-timeout 秒聯系不到后被認為該節點fail

 

cluster-require-full-coverage

## step 1 

## kill掉一個節點(主從都kill) 使其中一個節點的所有哈希槽不可用

 

 

 ##  cluster-require-full-coverage yes 的時候,當有哈希槽不可用(fail)的時候,集群不可用

 

##  cluster-require-full-coverage no的時候,當有哈希槽不可用(fail)的時候,集群仍然可用

## 該參數是實例配置的,所以,如果某個實例上該值為yes的時候,該節點仍然不可用

 

cluster-slave-no-failover

## step 1

## cluster nodes

## 在 7000 上設置 cluster-slave-no-failover yes

## kill掉7004的實例,觀察是否發生failover

 

 

 ## 當在slave 上設置 cluster-slave-no-failover yes 時,當該slave 的master fail時不會發生failover

 

cluster-migration-barrier 1

## redis-server /apps/conf/cluster/7006.conf

## 開起多一個實例

## cluster meet 127.0.0.1 7006

 

 

 

## 把127.0.0.1 7006實例加入集群

## cluster replicate 47bef6d030f33e5586f9611c336acce9df42023e

## 把該節點作為47bef6d030f33e5586f9611c336acce9df42023e的從節點

 

## kill 掉另外master 的的一個slave,讓該master 沒有slave,觀察日志

 

 

 

## 那些分配后仍然剩余migration barrier個從節點的主節點才會觸發節點分配,避免有主節點沒有從節點的情況

## 可見原來的7001 已經移動到沒有slave 的master 上面

 

5.查看Redis Cluster 狀態

cluster_state:ok    
## ok狀態表示集群可以正常接受查詢請求。fail 狀態表示,至少有一個哈希槽沒有被綁定

cluster_slots_assigned:16384
## 16384個哈希槽全部被分配到集群節點是集群正常運行的必要條件

cluster_slots_ok:16384
## 哈希槽正常的數量

cluster_slots_pfail:0
## 哈希槽狀態是 PFAIL的數量
## PFAIL狀態表示我們當前不能和節點進行交互,但這種狀態只是臨時的錯誤狀態
## 只要哈希槽狀態沒有被升級到FAIL狀態,這些哈希槽仍然可以被正常處理

cluster_slots_fail:0
## 哈希槽狀態是FAIL的數量。如果值不是0,那么集群節點將無法提供查詢服務
## 除非cluster-require-full-coverage被設置為no

cluster_known_nodes:6
## 集群中節點的數量

cluster_size:3
## 至少包含一個哈希槽且能夠提供服務的master節點數量

cluster_current_epoch:6
## 每次故障遷移會遞增,加 1

cluster_my_epoch:1
## 配置文件中Config Epoch的值

cluster_stats_messages_ping_sent:7298
## 該節點發送ping命令的次數

cluster_stats_messages_pong_sent:7047
## 當接收到ping、meet消息時,作為響應消息回復給發送方確認消息正常通信
## pong消息內部封裝了自身狀態數據
## 節點也可以向集群內廣播自身的pong消息來通知整個集群對自身狀態進行更新

cluster_stats_messages_sent:14345
## 通過node-to-node二進制總線發送的消息數量.

cluster_stats_messages_ping_received:7042
## 該節點收到的ping消息數量

cluster_stats_messages_pong_received:7298
## ## 該節點收到的pong消息數量
cluster_stats_messages_meet_received:5
## 用於通知新節點加入。消息發送者通知接收者加入到當前集群
## meet消息通信正常完成后,接收節點會加入到集群中並進行周期性的ping、pong消息交換

cluster_stats_messages_received:14345
## 通過node-to-node二進制總線接收的消息數量.

6.REDIS 內部機制

 

數據分片機制

一共有16384個哈希槽,用於存放數據,數據存放時,先執行CRC16 來計算放在哪個槽上,可以移動哈希槽來把熱點數據分散在不同節點上的來實現高效查詢的目的

節點間的內部通信機制

redis cluster節點間采取gossip協議進行通信,互相之間不斷通信,保持整個集群所有節點可用,好處在於,元數據的更新比較分散,不是集中在一個地方,更新請求會陸陸續續,打到所有節點上去更新,有一定的延時,降低了壓力。

每個節點都有一個專門用於節點間通信的端口,就是自己提供服務的端口號+10000,比如7001,那么用於節點間通信的就是17001端口

gossip協議包含多種消息,包括ping,pong,meet,fail,等等

meet: 某個節點發送meet給新加入的節點,讓新節點加入集群中,然后新節點就會開始與其他節點進行通信

ping: 每個節點都會頻繁給其他節點發送ping,其中包含自己的狀態還有自己維護的集群元數據,互相通過ping交換元數據,所以可能會加重網絡負擔

pong: 返回ping和meet,包含自己的狀態和其他信息,也可以用於信息廣播和更新

fail: 某個節點判斷另一個節點fail之后,就發送fail給其他節點,通知其他節點,指定的節點宕機了

主觀下線(pfail)

當cluster-node-timeout時間內沒有響應其他節點的ping消息,則被發送ping消息的節點認為已經下線

客觀下線(fail)

當某個節點判斷另一個節點主觀下線后,該節點的下線報告會通過Gossip消息傳播,ping給其他節點,如果超過半數的節點都認為pfail了,那么就會變成fail

 

准備選舉時間

有一定延遲,一定的延遲確保我們等待FAIL狀態在集群中傳播,slave如果立即嘗試選舉,其它masters或許尚未意識到FAIL狀態,可能會拒絕投票

延遲計算公式:

DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms

SLAVE_RANK表示此slave已經從master復制數據的總量的rank。Rank越小代表已復制的數據越新。這種方式下,持有最新數據的slave將會首先發起選舉(理論上)

資格檢查

如果cluster-slave-validity-factor開啟,則對客觀下線的slave進行資格檢查,(node-timeout * slave-validity-factor) + repl-ping-slave-period計算slave的數據是否過於陳舊

如果過於陳舊,則不允許升級為master

 

 選舉投票

只有持有槽的主節點才會處理故障選舉消息,每個持有槽的節點在一個配置紀元內都有唯一的一張選票,當接到第一個請求投票的從節點消息

 

 替換主節點

當前從節點取消復制變為主節點,撤銷故障主節點負責的槽,把這些槽委派給自己,並向集群廣播告知所有節點當前從節點變為主節點

當有一個master 宕機后,slave 可以檢測到master 宕機,同時另外帶槽的節點也能發現某master宕機,由宕機master 的slave 來發起選舉,但這個發起選舉有一定的延遲,如果slave立即嘗試選舉,其它masters或許尚未意識到FAIL狀態,可能會拒絕投票。同時這段時間其他帶槽的master 節點也會判斷該節點是否下線。故障遷移由選舉成功的slave來執行

 

7. CLUSTER 擴容

 

## step 1

## 查看現有節點和slot

## cluster -c -p 7000 cluster nodes

 

 

## step 2

## 新增新的master和slave節點來擴容

## redis-server /apps/conf/cluster/7003.conf

## redis-server /apps/conf/cluster/7005.conf

 

## step3 

## 把新增的節點加入集群

## redis-cli -p 7000 -c

## cluster meet 127.0.0.1 7003

## cluster meet 127.0.0.1 7005

## cluster nodes

 

 

## step 4

## 把槽分給新加入的master 節點

## redis-trib.rb reshard 127.0.0.1:7004 (任意槽節點就可以,主要是用來讓redis-trib.rb發現其他節點)

 

## 分配 5000個槽

## 接收節點 7005

## 分配槽的節點 7002

## done 執行

 

 ## 擴容成功

 

8. CLUSTER縮容

## step 1

## redis-cli -c -p 7000 cluster nodes

 

 

## 現在需要刪除一個節點,把它的所有slots分配到另外兩個節點上面,分配完后,該節點就沒有slot,就可以關閉該節點以及該節點的slave

## cluster要移除 master 127.0.0.1:7005 和slave的 127.0.0.1:7006

 

## step2

## redis-trib.rb del-node 127.0.0.1:7006 47bef6d030f33e5586f9611c336acce9df42023e

## cluster移除slave節點 

 

## step3

## 在kill master 服務前,需要先把master 上面的槽移動到其他master 上,避免在kill 掉master后,slot fail導致服務不可用

## redis-trib.rb reshard 127.0.0.1:7005 

## 執行這個命令讓槽從新分片,不一定要127.0.0.1:7005 ,這個隨便輸入一個節點都可以,主要是用來讓redis-trib.rb發現其他節點

 

## 選擇要移動多少個槽 484

## 選擇要接收這些槽的ID 

## 選擇從哪些槽中移出

## all 表示從除了接收槽的節點外所有擁有槽的節點移出共484個

## done 是先輸入指定要移出的槽 再輸入done ,在縮容時的選擇,移除指定節點的所有槽到其他節點

 

 ## 執行 redis-cli -c -p 7000 cluster nodes

## 可見7005節點上已經沒有槽了

## redis-trib.rb del-node 127.0.0.1:7005 47bef6d030f33e5586f9611c336acce9df42023e

## redis-cli -c -p 7000 cluster info 查看集群狀態

 

 

9.redis cluster 故障遷移

## 查看集群節點

## tail -f /apps/logs/redis/redis7004.log

## netstat -lnp | grep redis

 

 ## kill 18616 讓master 7002 下線,觀察日志

 ## 7004.log

 

18656:M 23 Apr 16:01:11.672 # Failover auth denied to b938dafab8ad824f622c3e20cfd594e50d465600: its master is up
## 拒絕從節點申請的故障遷移,該節點認為它的master 還存活,通信延遲

18656:M 23 Apr 16:01:12.047 * Marking node 25b52321824aa5e4616faf9a0723f2365ccb2ed6 as failing (quorum reached).
## 其他兩個master 都認為宕機master 已下線,客觀下線
18656:M 23 Apr 16:01:12.047 # Cluster state changed: fail
## 集群不可用
18656:M 23 Apr 16:02:12.533 # Failover auth granted to b938dafab8ad824f622c3e20cfd594e50d465600 for epoch 17
## 7004 投票給b938dafab8ad824f622c3e20cfd594e50d465600為下一個master
18656:M 23 Apr 16:02:12.573 # Cluster state changed: ok

## 7006.log   下線master 的slave

29436:S 23 Apr 16:02:11.329 # Error condition on socket for SYNC: Connection refused
## 和master 的連接失敗

29436:S 23 Apr 16:02:11.630 # Start of election delayed for 855 milliseconds (rank #0, offset 112324).
##選舉延遲855毫秒開始

29436:S 23 Apr 16:02:11.730 # Currently unable to failover: Waiting the delay before I can start a new failover.
## 此時不能執行failover, 等待延遲時間

29436:S 23 Apr 16:02:12.331 * Connecting to MASTER 127.0.0.1:7002
## 重新嘗試連接
29436:S 23 Apr 16:02:12.331 * MASTER <-> SLAVE sync started
29436:S 23 Apr 16:02:12.331 # Error condition on socket for SYNC: Connection refused
## 連接失敗

29436:S 23 Apr 16:02:12.532 # Starting a failover election for epoch 17.
## 開始選舉, 17 變更次數,版本號
29436:S 23 Apr 16:02:12.534 # Failover election won: I'm the new master.
## 該slave節點選舉成功,成為master
29436:S 23 Apr 16:02:12.534 # configEpoch set to 17 after successful failover
## 當前版本號設置成17
29436:M 23 Apr 16:02:12.534 # Setting secondary replication ID to 13c1513e8578dffb8961af0be28d44d1ed080081, valid up to offset: 112325. New replication ID is 8a088a369e4de2a3630f903bfe7ae88e56d17d7d
## 給當前節點設置新的replid 和偏移量

29436:M 23 Apr 16:02:12.534 * Discarding previously cached master state.
29436:M 23 Apr 16:02:12.534 # Cluster state changed: ok
## cluster 狀態可用

9. 為什么cluster 設置16384個槽

CRC16 本身產生的hash key大小為16bit ,可以存儲的值的個數為2的16次方,為65536,是16384 的4倍

節點之間需要相互通信,發送心跳包,心跳包里面包含着節點的槽信息

這個槽的信息用了bitmap

假如要判斷0-89個數中4-6存不存在,就可以用9個bit來表示這9個數,1Byte = 8bit,在二進制中 8個二進制位等於 1Byte, 也就是說一個 1BIT 等於一個二進制位,一個二進制位只能表示1 和 0,剛好,1表示這個數存在,0表示這個數不存在

所以16384 個數可以用 16384個bit來表示該節點有哪些槽 也就是 2048 Byte(16384/8)=2kb

如果65536就是 8kb了,也就是說如果設置65536個槽 每個心跳包都太大了。至少每個包都至少要8kb

redis集群內節點,每秒都在發ping消息。規律如下

  • (1)每秒會隨機選取5個節點,找出最久沒有通信的節點發送ping消息
  • (2)每100毫秒(1秒10次)都會掃描本地節點列表,如果發現節點最近一次接受pong消息的時間大於cluster-node-timeout/2 則立刻發送ping消息

按這種頻率發 每個包至少8kb 影響性能

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM