1. 程式人生 > 實用技巧 >cluster模式04

cluster模式04

Redis Cluster 分散式叢集

參考網站

1.什麼是Redis Cluster

1.Redis叢集是一個可以在'多個Redis節點'之間進行'網路互聯,資料共享'
2.Redis叢集不支援那些需要'同時處理多個鍵'的Redis命令,因為執行這些命令需要在'多個Redis節點之間'移動資料,並且在高負載的情況下,這些命令將降低Redis叢集的效能,並導致不可預測的行為。(#使用ack協議可以實現)
3.Redis叢集通過'分割槽'(partition)來提供一定程度的可用性(availability):即使叢集中有一部分節點失效或者無法進行通訊,叢集也可以繼續處理命令請求。(#sentinel)
4.Redis叢集有'將資料自動切分'(split)到多個節點的能力。(#儲存)
5.所有的節點都是一主一從(也可以是一主多從),其中'從不提供服務',僅作為備用


sentinel模式基本可以滿足一般生產的需求,具備高可用性。但是當資料量過大到一臺伺服器存放不下的情況時,主從模式或sentinel模式就不能滿足需求了,這個時候需要對儲存的資料進行分片,將資料儲存到多個Redis例項中。'cluster模式的出現就是為了解決單機Redis容量有限的問題',將Redis的資料根據一定的規則分配到多臺機器。

'cluster可以說是sentinel和主從模式的結合體',通過cluster可以實現主從和master重選功能,所以如果配置兩個副本三個分片的話,就需要六個Redis例項。因為Redis的資料是根據一定規則分配到cluster的不同機器的,當資料量過大時,'可以新增機器進行擴容。'

使用叢集,只需要將redis配置檔案中的'cluster-enable配置開啟'即可。每個叢集中至少需要三個主資料庫才能正常執行,新增節點非常方便(#支援線上增加、刪除節點)

叢集中的每個節點都是'平等'的關係,都是對等的,每個節點都'儲存'各自的資料和整個叢集的狀態。每個節點都和其他'所有節點連線',而且這些連線保持活躍,這樣就保證了我們只需要連線叢集中的任意一個節點,就可以獲取到其他節點的資料。

Redis 叢集沒有並使用傳統的'一致性雜湊'來'分配資料',而是採用另外一種叫做'雜湊槽 '(hash slot)的方式來分配的

Redis 叢集會把資料存在一個 master 節點,然後在這個 master 和其對應的salve 之間進行資料同步。當讀取資料時,也根據一致性雜湊演算法到對應的 master 節點獲取資料。只有當一個master 掛掉之後,才會'啟動一個對應的 salve 節點,充當 master 。'

必須要'3個或以上的主節點',否則在建立叢集時會失敗,並且當存活的主節點數小於總節點數的一半時,整個叢集就無法提供服務了。

2.Redis Cluster的特點

#高效能:
1.在多分片節點中,將'16384'個槽位,均勻分佈到多個'分片節點'中
2.存資料時,將key做crc16(key),然後和16384進行'取模',得出'槽位值'(0-16384之間)
3.根據計算得出的槽位值,找到相對應的'分片節點的主節點','儲存'到相應槽位上(ask協議)
4.如果客戶端當時連線的節點不是將來要儲存的分片節點,分片叢集會將客戶端連線切換至真正儲存節點進行資料儲存
5.客戶端與redis節點'直連',不需要中間proxy層(不做讀寫分離的時候).'客戶端'不需要連線叢集所有節點,連線'叢集中任何一個可用節點'即可進行讀寫
6.Redis Cluster解決了redis'資源利用率'的問題

#高可用
7.在搭建叢集時,會為每一個分片的'主節點',對應一個'從節點',實現slaveof功能,同時當主節點down,實現類似於sentinel的自動failover的功能。

3.槽的概念

1.在叢集中,會把所有節點分為'16384'個槽位(#即空間)
2.槽位的序號是 0 - 16383,序號不重要,'數量'才重要
3.每一個槽位分配到資料的'概率'是一樣

4.redis故障轉移

1.在叢集裡面,'節點會對其他節點'進行下線檢測。
2.當一個主節點下線時,叢集裡面的'其他主節點負責對下線主節點'進行故障轉移。
3.換句話說,叢集的'節點'集成了'下線檢測和故障轉移'等類似 Sentinel 的功能。

redis叢集搭建

1.環境準備

節點 IP
節點1 172.16.1.51 6379,6380
節點2 172.16.1.52 6379,6380
節點3 172.16.1.53 6379,6380

2.搭建redis

#刪除以前的redis資料
[root@db01 ~]# rm -rf /service/redis/*

#建立多例項目錄
[root@db01 ~]# mkdir /service/redis/{6379,6380}
[root@db02 ~]# mkdir /service/redis/{6379,6380}
[root@db03 ~]# mkdir /service/redis/{6379,6380}

#配置所有redis
[root@db01 ~]# vim /service/redis/6379/redis.conf
bind 172.16.1.51 127.0.0.1
port 6379
daemonize yes
pidfile /service/redis/6379/redis.pid
loglevel notice
logfile /service/redis/6379/redis.log
dbfilename dump.rdb
dir /service/redis/6379
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000

[root@db01 ~]# vim /service/redis/6380/redis.conf
bind 172.16.1.51 127.0.0.1
port 6380
daemonize yes
pidfile /service/redis/6380/redis.pid
loglevel notice
logfile /service/redis/6380/redis.log
dbfilename dump.rdb
dir /service/redis/6380
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000

3.啟動所有redis

[root@db01 ~]# redis-server /service/redis/6379/redis.conf 
[root@db01 ~]# redis-server /service/redis/6380/redis.conf

[root@db02 ~]# redis-server /service/redis/6379/redis.conf 
[root@db02 ~]# redis-server /service/redis/6380/redis.conf

[root@db03 ~]# redis-server /service/redis/6379/redis.conf 
[root@db03 ~]# redis-server /service/redis/6380/redis.conf

4.關聯所有redis節點(1.使用ruby 2.使用命令)

1)登入所有節點

[root@db01 ~]# redis-cli -h 172.16.1.51 -p 6379
[root@db01 ~]# redis-cli -h 172.16.1.51 -p 6380
[root@db02 ~]# redis-cli -h 172.16.1.52 -p 6379
[root@db02 ~]# redis-cli -h 172.16.1.52 -p 6380
[root@db03 ~]# redis-cli -h 172.16.1.53 -p 6379
[root@db03 ~]# redis-cli -h 172.16.1.53 -p 6380

2)檢視叢集節點

#檢視叢集節點,每一各節點只能看到自己
172.16.1.51:6379> CLUSTER NODES
28faba09f4c0ec8cdb90d92e09636796427b7143 :6379 myself,master - 0 0 0 connected

該節點id	埠	myself(關聯源)	主庫或者從庫 槽位

3)關聯所有節點(使用ruby安裝不需要使用該命令關聯)

172.16.1.51:6379> CLUSTER MEET 172.16.1.51 6380
OK
172.16.1.51:6379> CLUSTER MEET 172.16.1.52 6379
OK
172.16.1.51:6379> CLUSTER MEET 172.16.1.52 6380
OK
172.16.1.51:6379> CLUSTER MEET 172.16.1.53 6379
OK
172.16.1.51:6379> CLUSTER MEET 172.16.1.53 6380
OK

#檢視叢集狀態,所有節點
172.16.1.51:6379> CLUSTER NODES
aee9f4e6e09a452fd44bca7639be442b5138f141 172.16.1.52:6380 master - 0 1596687131655 4 connected
777412c8d6554e3390e1083bf1f55002be08cf62 172.16.1.51:6380 master - 0 1596687131352 2 connected
ef18ab5bab6d8bc06917a0cf2dc9bffa8b431087 172.16.1.52:6379 master - 0 1596687132362 3 connected
f2747c92813ea06b25c3e9c8d5232b46b3cf9d3d 172.16.1.53:6379 master - 0 1596687131856 0 connected
25f735f08ac62b2f758c1e2c21e178cc46279087 172.16.1.53:6380 master - 0 1596687131251 5 connected
28faba09f4c0ec8cdb90d92e09636796427b7143 172.16.1.51:6379 myself,master - 0 0 1 connected

當前節點的id 	當前例項ip+埠	主從狀態  [主庫id]	0    時間戳   序號	連線狀態
#不能刪除關聯,只能取消節點

5.分配槽位

#檢視叢集狀態
172.16.1.51:6379> CLUSTER INFO
cluster_state:fail				#失敗
cluster_slots_assigned:0		#叢集槽位	
cluster_slots_ok:0				#可用槽位
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6			#節點數
cluster_size:0					#叢集資料大小
cluster_current_epoch:5
cluster_my_epoch:1
cluster_stats_messages_sent:1168
cluster_stats_messages_received:1168

#槽位規劃,一共16383個槽位
db01:     5462 個槽位  (0-5461)
db02:     5462 個槽位  (5462-10922)
db03:	  5461 個槽位  (10923-16383)

#分配槽位(命令列執行),不能多,不能少,一共16384個槽位
[root@db01 ~]# redis-cli -p 6379 -h 172.16.1.51 CLUSTER ADDSLOTS {0..5461}
OK
[root@db02 ~]# redis-cli -p 6379 -h 172.16.1.52 CLUSTER ADDSLOTS {5462..10922}
OK
[root@db02 ~]# redis-cli -p 6379 -h 172.16.1.53 CLUSTER ADDSLOTS {10923..16383}

刪除槽位
[root@db02 ~]# redis-cli -p 6379 cluster delslots {0..16383}

#槽位分配錯誤,需要刪除node.conf,後重啟Redis,再重新使用CLUSTER MEET關聯,再分配槽位(該節點記錄當前叢集的節點資訊)
[root@db04 ~]# vim /service/redis/6379/nodes.conf

#沒有槽位(資料)的例項不參與主從切換,要重新分配槽位才能以主庫的身份加入叢集,從而達到擴容的目的
#刪除槽位就會刪除資料,可以直接使用命令redis-trib.rb分配槽位
#槽位沒有順序,資料的儲存只與槽位的數量有關
#槽位分配之後,使用redis-cli -c -a 123 -p 6379連線Redis,插入資料
#cluster模式下,主庫的存在是為了擴容,從庫(副本)的作用是隻是為了成為主庫
#分散式配置Redis cluster模式交叉配置主從是為了增加主機的容錯率

6.檢視槽位分配

172.16.1.52:6380> CLUSTER NODES
98426a9d82a79dd8ba036dab1463cb8b5523982f 172.16.1.54:6380 master - 0 1596713561103 3 connected
a5cf44b0c71e627620b711432c1eae11055213f1 172.16.1.53:6379 master - 0 1596713562614 5 connected 5462-10922
8be7332c63673348dddad9f74a7d8eb755bd80be 172.16.1.54:6379 master - 0 1596713562108 4 connected 10923-16383
a61b28d8b590196cbef8fca3d7cfe69569983733 172.16.1.53:6380 master - 0 1596713563117 2 connected
b5ac2f2b8bc626362abf83e745e5351f5f94984d 172.16.1.52:6379 master - 0 1596713561606 1 connected 0-5461
f9f5d2d335ce56b6d787b99200049c7e04c8ec21 172.16.1.52:6380 myself,master - 0 0 0 connected
#叢集中主庫從庫應該有相同的配置
#一個主庫可以有多個從庫,一個從庫只能有一個主庫(因為他有可能成為主庫,槽位不能混亂)
#合理的做了副本之後,一臺例項down,不影響叢集狀態,down-->up ,該主機上的例項將自動以從庫的身份加入叢集
#叢集中增加節點,自動以主庫身份加入,可以使用CLUSTER REPLICATE命令,把主庫變為從庫
#不能取消關聯,但是可以刪除節點
	無法刪除登入節點
	不能刪除自己的master節點,可以刪除其它的master節點,可以刪除其它的slave節點
#將節點配置資訊儲存到硬碟
CLUSTER SAVECONFIG              

批量插入資料

[root@db02 ~]# vim kv.sh
#!/bin/bash
for i in {1..1000};do
        redis-cli -c -a 123 -p 6379 -h 172.16.1.52 set k${i} v${i}
done

執行
[root@db02 ~]# sh kv.sh 

檢視每臺Redis資料的數量
127.0.0.1:6379> DBSIZE
(integer) 342

7.新增副本節點(配置主從)

1)檢視節點

172.16.1.51:6379> CLUSTER NODES
5a7f0cf95e1850b5b5ae81d873c4c76fd366d604 172.16.1.51:6380 master - 0 1596763193422 4 connected
5eb9e5356534ff4acda736d13f0dc9fc3d40049b 172.16.1.52:6379 master - 0 1596763192412 5 connected 5462-10922
50878ef6a4d8141c8dbca3e2bf7c84ed48a73ee2 172.16.1.53:6380 master - 0 1596763192512 3 connected
acc3a4d0e6e43fc74630c1f0714865fdcbdaf677 172.16.1.53:6379 master - 0 1596763191908 0 connected 10923-16383
2325be6f1f9c1c9f57d5a033fc05e0d798ea823a 172.16.1.51:6379 myself,master - 0 0 1 connected 0-5461
381b54584572e8013becdae2eeaff48bf6eb5450 172.16.1.52:6380 master - 0 1596763193925 2 connected

2)配置主從

#db01的6380做db02的6379的從庫
172.16.1.51:6380> CLUSTER REPLICATE 5eb9e5356534ff4acda736d13f0dc9fc3d40049b
OK

#db02的6380做db03的6379的從庫
172.16.1.52:6380> CLUSTER REPLICATE acc3a4d0e6e43fc74630c1f0714865fdcbdaf677
OK

#db03的6380做db01的6379的從庫
172.16.1.53:6380> CLUSTER REPLICATE 2325be6f1f9c1c9f57d5a033fc05e0d798ea823a
OK

3)再次檢視節點資訊

172.16.1.51:6379> CLUSTER NODES
5a7f0cf95e1850b5b5ae81d873c4c76fd366d604 172.16.1.51:6380 slave 5eb9e5356534ff4acda736d13f0dc9fc3d40049b 0 1596763362696 5 connected
5eb9e5356534ff4acda736d13f0dc9fc3d40049b 172.16.1.52:6379 master - 0 1596763363202 5 connected 5462-10922
50878ef6a4d8141c8dbca3e2bf7c84ed48a73ee2 172.16.1.53:6380 slave 2325be6f1f9c1c9f57d5a033fc05e0d798ea823a 0 1596763362192 3 connected
acc3a4d0e6e43fc74630c1f0714865fdcbdaf677 172.16.1.53:6379 master - 0 1596763363203 0 connected 10923-16383
2325be6f1f9c1c9f57d5a033fc05e0d798ea823a 172.16.1.51:6379 myself,master - 0 0 1 connected 0-5461
381b54584572e8013becdae2eeaff48bf6eb5450 172.16.1.52:6380 slave acc3a4d0e6e43fc74630c1f0714865fdcbdaf677 0 1596763364211 2 connected

master後面是 - 
slave後面是主庫的id
#主庫的作用是擴容,從庫的作用是增加叢集的容錯率

8.故障演示

#停掉一臺節點
[root@db03 ~]# reboot

#到另一臺機器檢視叢集狀態,發現叢集是正常的
172.16.1.51: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:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_sent:327031
cluster_stats_messages_received:326973

#檢視節點資訊,副本被提升為主庫
172.16.1.51:6379> CLUSTER NODES
5a7f0cf95e1850b5b5ae81d873c4c76fd366d604 172.16.1.51:6380 slave 5eb9e5356534ff4acda736d13f0dc9fc3d40049b 0 1596763771309 5 connected
5eb9e5356534ff4acda736d13f0dc9fc3d40049b 172.16.1.52:6379 master - 0 1596763771310 5 connected 5462-10922
50878ef6a4d8141c8dbca3e2bf7c84ed48a73ee2 172.16.1.53:6380 slave,'fail' 2325be6f1f9c1c9f57d5a033fc05e0d798ea823a 1596763736458 1596763734245 3 disconnected
acc3a4d0e6e43fc74630c1f0714865fdcbdaf677 172.16.1.53:6379 master,'fail' - 1596763736458 1596763735246 0 disconnected
2325be6f1f9c1c9f57d5a033fc05e0d798ea823a 172.16.1.51:6379 myself,master - 0 0 1 connected 0-5461
381b54584572e8013becdae2eeaff48bf6eb5450 172.16.1.52:6380 master - 0 1596763772319 6 connected 10923-16383

9.節點恢復

#修復機器
[root@db03 ~]# redis-server /service/redis/6379/redis.conf 
[root@db03 ~]# redis-server /service/redis/6380/redis.conf

#再次檢視節點資訊
172.16.1.51:6379> CLUSTER NODES
5a7f0cf95e1850b5b5ae81d873c4c76fd366d604 172.16.1.51:6380 slave 5eb9e5356534ff4acda736d13f0dc9fc3d40049b 0 1596764061287 5 connected
5eb9e5356534ff4acda736d13f0dc9fc3d40049b 172.16.1.52:6379 master - 0 1596764060781 5 connected 5462-10922
50878ef6a4d8141c8dbca3e2bf7c84ed48a73ee2 172.16.1.53:6380 'slave '2325be6f1f9c1c9f57d5a033fc05e0d798ea823a 0 1596764059770 3 connected
acc3a4d0e6e43fc74630c1f0714865fdcbdaf677 172.16.1.53:6379 'slave' 381b54584572e8013becdae2eeaff48bf6eb5450 0 1596764062094 6 connected
2325be6f1f9c1c9f57d5a033fc05e0d798ea823a 172.16.1.51:6379 myself,master - 0 0 1 connected 0-5461
381b54584572e8013becdae2eeaff48bf6eb5450 172.16.1.52:6380 master - 0 1596764061789 6 connected 10923-16383

#原主節點修復後變為從節點