redis 5.0 叢集的安裝

czxin788發表於2019-03-01

redis cluster簡介

Redis 叢集沒有使用一致性hash, 而是引入了 雜湊槽的概念.

Redis 叢集有16384個雜湊槽,每個key透過CRC16校驗後對16384取模來決定放置哪個槽.叢集的每個節點負責一部分hash槽,舉個例子,比如當前叢集有3個節點,那麼:

節點 A 包含 0 到 5500號雜湊槽.

節點 B 包含5501 到 11000 號雜湊槽.

節點 C 包含11001 到 16384號雜湊槽.

這種結構很容易新增或者刪除節點. 比如如果我想新新增個節點D, 我需要從節點 A, B, C中得部分槽到D上. 如果我想移除節點A,需要將A中的槽移到B和C節點上,然後將沒有任何槽的A節點從叢集中移除即可. 由於從一個節點將雜湊槽移動到另一個節點並不會停止服務,所以無論新增刪除或者改變某個節點的雜湊槽的數量都不會造成叢集不可用的狀態.


圖中描述的是六個redis例項構成的叢集

6379埠為客戶端通訊埠

16379埠為叢集匯流排埠

叢集內部劃分為16384個資料分槽,分佈在三個主redis中。

從redis中沒有分槽,不會參與叢集投票,也不會幫忙加快讀取資料,僅僅作為主機的備份。

三個主節點中平均分佈著16384資料分槽的三分之一,每個節點中不會存有有重複資料,僅僅有自己的從機幫忙冗餘。

注意:redis cluster至少要有三個主節點,為了冗餘,至少還要有三個從節點。


為了使在部分節點失敗或者大部分節點無法通訊的情況下叢集仍然可用,所以叢集使用了主從複製模型,每個節點都會有N-1個複製品.

在我們例子中具有A,B,C三個節點的叢集,在沒有複製模型的情況下,如果節點B失敗了,那麼整個叢集就會以為缺少5501-11000這個範圍的槽而不可用.

然而如果在叢集建立的時候(或者過一段時間)我們為每個節點新增一個從節點A1,B1,C1,那麼整個叢集便有三個master節點和三個slave節點組成,這樣在節點B失敗後,叢集便會選舉B1為新的主節點繼續服務,整個叢集便不會因為槽找不到而不可用了。

不過當B和B1 都失敗後,叢集是不可用的.

Redis 一致性保證

Redis 並不能保證資料的強一致性. 這意味這在實際中叢集在特定的條件下可能會丟失寫操作.

第一個原因是因為叢集是用了非同步複製. 寫操作過程:

客戶端向主節點B寫入一條命令.

主節點B向客戶端回覆命令狀態.

主節點將寫操作複製給他得從節點 B1, B2 和 B3.

主節點對命令的複製工作發生在返回命令回覆之後, 因為如果每次處理命令請求都需要等待複製操作完成的話, 那麼主節點處理命令請求的速度將極大地降低 —— 我們必須在效能和一致性之間做出權衡。 注意:Redis 叢集可能會在將來提供同步寫的方法。 

Redis 叢集另外一種可能會丟失命令的情況是叢集出現了網路分割槽 , 並且一個客戶端與至少包括一個主節點在內的少數例項被孤立。

舉個例子 假設叢集包含 A 、 B 、 C 、 A1 、 B1 、 C1 六個節點, 其中 A 、B 、C 為主節點, A1 、B1 、C1 為A,B,C的從節點, 還有一個客戶端 Z1 假設叢集中發生網路分割槽,那麼叢集可能會分為兩方,大部分的一方包含節點 A 、C 、A1 、B1 和 C1 ,小部分的一方則包含節點 B 和客戶端 Z1 .

Z1仍然能夠向主節點B中寫入, 如果網路分割槽發生時間較短,那麼叢集將會繼續正常運作,如果分割槽的時間足夠讓大部分的一方將B1選舉為新的master,那麼Z1寫入B中得資料便丟失了.

注意, 在網路分裂出現期間, 客戶端 Z1 可以向主節點 B 傳送寫命令的最大時間是有限制的, 這一時間限制稱為節點超時時間(cluster-node-timeout), 是 Redis 叢集的一個重要的配置選項:

準備好兩臺虛擬機器

node1:172.18.22.100
node2:172.18.22.101

下載最新版redis 5.0安裝包

我下載的是redis-5.0.3.tar.gz

編譯安裝(node1)

[root@node1 ~]# cd /opt/
[root@node1 opt]# tar -xvf redis-5.0.3.tar.gz
[root@node1 opt]# cd redis-5.0.3/
[root@node1 opt]# make MALLOC=lib
[root@node1 opt]# make install

修改配置檔案,複製到其他機器上

node1伺服器上:
[root@node1 ~]# cd /opt/
[root@node1 opt]# tar -xvf redis-5.0.3.tar.gz
[root@node1 opt]# cd redis-5.0.3/
[root@node1 redis-5.0.3]# mkdir -p redis_cluster/7000/data
[root@node1 redis-5.0.3]# mkdir -p redis_cluster/7001/data
[root@node1 redis-5.0.3]# mkdir -p redis_cluster/7002/data

在上面的三個目錄裡面建立redis.conf檔案,需要修改的地方下面已經標註:

#redis.conf預設配置
daemonize yes
############多例項情況下需修改,例如redis_6380.pid
pidfile /var/run/redis_7000.pid
##############多例項情況下需要修改,例如6380
port 7000
tcp-backlog 511
bind 0.0.0.0
timeout 0
tcp-keepalive 0
loglevel notice
###################多例項情況下需要修改,例如6380.log
logfile /var/log/redis_7000.log
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
##################多例項情況下需要修改,例如dump.6380.rdb
dbfilename dump.7000.rdb
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
appendonly yes
#######################多例項情況下需要修改,例如 appendonly_6380.aof
appendfilename "appendonly_7000.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
#系統配置
#vim /etc/sysctl.conf
#vm.overcommit_memory = 1
#自定義配置
aof-rewrite-incremental-fsync yes
maxmemory 4096mb
maxmemory-policy allkeys-lru
######################多例項情況下需要修改,例如/data/6380
dir /opt/redis-5.0.3/redis_cluster/7000/data
#叢集配置
cluster-enabled yes
######################多例項情況下需要修改
cluster-config-file /opt/redis-5.0.3/redis_cluster/7000/nodes.conf
cluster-node-timeout 5000
#從ping主間隔預設10秒
#複製超時時間
#repl-timeout 60
#遠距離主從
#config set client-output-buffer-limit "slave 536870912 536870912 0"
#config set repl-backlog-size 209715200

[root@node1 redis-5.0.3]# scp -pr /opt/redis-5.0.3/ node2:/opt/

cluster-node-timeout這個引數很重要,設定太小,會頻繁發生主從自動切換,設定時間太大,會發生主當機了,不能及時進行主從切換。

一旦某個主節點進入了FAIL狀態,如果這個主節點有一個或者多個從節點存在,那麼其中一個從節點會被升級為主節點,而其它從節點會開始對這個新主節點進行復制

啟動命令,在node1和node2上執行

[root@node1 redis-5.0.3]# /opt/redis-5.0.3/src/redis-server /opt/redis-5.0.3/redis_cluster/7000/redis.conf
[root@node1 redis-5.0.3]# /opt/redis-5.0.3/src/redis-server /opt/redis-5.0.3/redis_cluster/7001/redis.conf 
[root@node1 redis-5.0.3]# /opt/redis-5.0.3/src/redis-server /opt/redis-5.0.3/redis_cluster/7002/redis.conf 
備註:
[root@node1 redis-5.0.3]#  /opt/redis-5.0.3/src/redis-cli -h localhost -p 7000 shutdown
[root@node1 redis-5.0.3]# /opt/redis-5.0.3/src/redis-cli -h localhost -p 7000 -c
localhost:7000> ping
PONG

備註: -c是啟動叢集模式


建立叢集命令

[root@node1 opt]# /opt/redis-5.0.3/src/redis-cli --cluster create 172.18.22.100:7000 172.18.22.100:7001 172.18.22.100:7002 172.18.22.101:7000 172.18.22.101:7001 172.18.22.101:7002 --cluster-replicas 1

中間要輸入一次yes。

選項–replicas 1 表示我們希望為叢集中的每個主節點建立一個從節點。

檢視叢集資訊

[root@node1 opt]# /opt/redis-5.0.3/src/redis-cli -h localhost -p 7001
localhost:7001> 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:2
cluster_stats_messages_ping_sent:1302
cluster_stats_messages_pong_sent:946
cluster_stats_messages_meet_sent:4
cluster_stats_messages_sent:2252
cluster_stats_messages_ping_received:945
cluster_stats_messages_pong_received:1306
cluster_stats_messages_meet_received:1
cluster_stats_messages_received:2252
localhost:7001>
localhost:7001> CLUSTER NODES
ed9ac7cfe6847f39dfcf56ad4244c4213a0965b1 172.18.22.100:7002@17002 slave f881aa4c6fdce6f7ac058600ca712fd9df110b1a 0 1551346045000 4 connected
fb56d260650dfad25e6b54c1519e9530e1b33b62 172.18.22.100:7001@17001 myself,master - 0 1551346046000 2 connected 10923-16383
09f371cfd0933a343dd6d84159a6f8ad508b1eff 172.18.22.100:7000@17000 master - 0 1551346047131 1 connected 0-5460
a7573d643ede9facb1e9b3b629a1604ed88b6a61 172.18.22.101:7002@17002 slave fb56d260650dfad25e6b54c1519e9530e1b33b62 0 1551346046000 6 connected
f881aa4c6fdce6f7ac058600ca712fd9df110b1a 172.18.22.101:7000@17000 master - 0 1551346046629 4 connected 5461-10922
8d3b210324f24aac0c146363e95d3c87a7eb474c 172.18.22.101:7001@17001 slave 09f371cfd0933a343dd6d84159a6f8ad508b1eff 0 1551346045627 5 connected


叢集驗證

在第一臺機器上連線叢集的7000埠的節點,在另外一臺連線7002節點,連線方式為 redis-cli -h localhost -c -p 7002 ,

加引數 -C 可連線到叢集。

在7000節點執行命令  set hello world ,執行結果如下:

localhost:7000> set hello world
OK
localhost:7000> get hello
"world"

然後在另外一臺7002埠,檢視 key 為 hello 的內容, get hello  ,執行結果如下:

localhost:7002> get hello
-> Redirected to slot [866] located at 172.18.22.100:7000
"world"

說明叢集運作正常。

簡單說一下原理

    redis cluster在設計的時候,就考慮到了去中心化,去中介軟體,也就是說,叢集中的每個節點都是平等的關係,都是對等的,

每個節點都儲存各自的資料和整個叢集的狀態。每個節點都和其他所有節點連線,而且這些連線保持活躍,這樣就保證了我

們只需要連線叢集中的任意一個節點,就可以獲取到其他節點的資料。

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

    redis cluster 預設分配了 16384 個slot,當我們set一個key 時,會用CRC16演算法來取模得到所屬的slot,然後將這個key 

分到雜湊槽區間的節點上,具體演算法就是:CRC16(key) % 16384。 所以我們在測試的時候看到set 和 get 的時候,直接跳轉

到了7000埠的節點。

    Redis 叢集會把資料存在一個 master 節點, 然後在這個 master 和其對應的salve 之間進行資料同步。當讀取資料時,

也根據一致性雜湊演算法到對應的 master 節點獲取資料。只有當一個master 掛掉之後,才會啟動一個對應的 salve 節點,

充當 master 。

    需要注意的是:必須要3個或以上的主節點,否則在建立叢集時會失敗,並且當存活的主節點數小於總節點數的一半時,

整個叢集就無法提供服務了。



參考文件:

https://www.cnblogs.com/wuxl360/p/5920330.html





來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28916011/viewspace-2637184/,如需轉載,請註明出處,否則將追究法律責任。

相關文章