Redis Cluster

轉 https://www.cnblogs.com/wxd0108/p/5798498.htmlphp

 

前言

redis 是咱們目前大規模使用的緩存中間件,因爲它強大高效而又便捷的功能,獲得了普遍的使用。如今的2.x的穩定版本是2.8.19,也是咱們項目中廣泛用到的版本。css

redis在年初發布了3.0.0,官方支持了redis cluster,也就是集羣。至此結束了redis 沒有官方集羣的時代,以前咱們用redis cluster用的最多的應該是twitter 發佈的Twemproxy(https://github.com/twitter/twemproxy)html

還有就是豌豆莢開發的codis (https://github.com/wandoulabs/codis)node

這2個我會在後續去使用它們。下面的文字,我儘可能用通熟易懂的方式來闡述。ios

 

redis cluster 理論知識

截止寫這篇文章前,redis 3.x的最新版本是3.0.5。今天的學習和實踐就是用這個版本。git

 

Redis Cluster設計要點

redis cluster在設計的時候,就考慮到了去中心化,去中間件,也就是說,集羣中的每一個節點都是平等的關係,都是對等的,每一個節點都保存各自的數據和整個集羣的狀態。每一個節點都和其餘全部節點鏈接,並且這些鏈接保持活躍,這樣就保證了咱們只須要鏈接集羣中的任意一個節點,就能夠獲取到其餘節點的數據。github

那麼redis 是如何合理分配這些節點和數據的呢?web

Redis 集羣沒有並使用傳統的一致性哈希來分配數據,而是採用另一種叫作哈希槽 (hash slot)的方式來分配的。redis cluster 默認分配了 16384 個slot,當咱們set一個key 時,會用CRC16算法來取模獲得所屬的slot,而後將這個key 分到哈希槽區間的節點上,具體算法就是:CRC16(key) % 16384redis

注意的是:必需要3個之後的主節點,不然在建立集羣時會失敗,咱們在後續會實踐到。算法

因此,咱們假設如今有3個節點已經組成了集羣,分別是:A, B, C 三個節點,它們能夠是一臺機器上的三個端口,也能夠是三臺不一樣的服務器。那麼,採用哈希槽 (hash slot)的方式來分配16384個slot 的話,它們三個節點分別承擔的slot 區間是:

  • 節點A覆蓋0-5460;
  • 節點B覆蓋5461-10922;
  • 節點C覆蓋10923-16383.

以下圖所示:

這裏寫圖片描述

那麼,如今我想設置一個key ,好比叫my_name:

set my_name yangyi

按照redis cluster的哈希槽算法:CRC16('my_name')%16384 = 2412。 那麼就會把這個key 的存儲分配到 A 上了。

一樣,當我鏈接(A,B,C)任何一個節點想獲取my_name這個key時,也會這樣的算法,而後內部跳轉到B節點上獲取數據。

這種哈希槽的分配方式有好也有壞,好處就是很清晰,好比我想新增一個節點D,redis cluster的這種作法是從各個節點的前面各拿取一部分slot到D上,我會在接下來的實踐中實驗。大體就會變成這樣:

  • 節點A覆蓋1365-5460
  • 節點B覆蓋6827-10922
  • 節點C覆蓋12288-16383
  • 節點D覆蓋0-1364,5461-6826,10923-12287

一樣刪除一個節點也是相似,移動完成後就能夠刪除這個節點了。

因此redis cluster 就是這樣的一個形狀:

這裏寫圖片描述

 

Redis Cluster主從模式

redis cluster 爲了保證數據的高可用性,加入了主從模式,一個主節點對應一個或多個從節點,主節點提供數據存取,從節點則是從主節點拉取數據備份,當這個主節點掛掉後,就會有這個從節點選取一個來充當主節點,從而保證集羣不會掛掉。

上面那個例子裏, 集羣有ABC三個主節點, 若是這3個節點都沒有加入從節點,若是B掛掉了,咱們就沒法訪問整個集羣了。A和C的slot也沒法訪問。

因此咱們在集羣創建的時候,必定要爲每一個主節點都添加了從節點, 好比像這樣, 集羣包含主節點A、B、C, 以及從節點A一、B一、C1, 那麼即便B掛掉系統也能夠繼續正確工做。

B1節點替代了B節點,因此Redis集羣將會選擇B1節點做爲新的主節點,集羣將會繼續正確地提供服務。 當B從新開啓後,它就會變成B1的從節點。

不過須要注意,若是節點B和B1同時掛了,Redis集羣就沒法繼續正確地提供服務了。

流程下圖所示:

這裏寫圖片描述

 

redis cluster 動手實踐

網上有不少教程,我最早是按照這個教程(http://blog.51yip.com/nosql/1725.html) 一步步的按照這個教程來,但是在最後啓動集羣的時候第一臺機器的6379端口死活啓動不了,這樣就沒有3臺主服務器,就完成不了集羣。最後也沒找到解決辦法。[知道緣由了:我把redis-trib.rb create --replicas 1的 這個1沒有寫!!!!]

如今,仍是按照官方的教程,全程再演示一次,官方教程是在一臺機器上啓動6個節點,3個當主,3個當從(http://redis.io/topics/cluster-tutorial):

先下載官方的redis 版本(3.0.5) : http://download.redis.io/releases/redis-3.0.5.tar.gz

下載不了,請自行FQ。我此次是在centos6.5上演示,用的是root 帳戶。

若是以前已經下載了redis的 2.x版本,只須要將 /usr/local/bin/redis-* 這幾個命令先刪除便可。

 

1.解壓

[root@web3 ~]# tar zxvf redis-3.0.5.tar.gz

2.安裝

[root@web3 ~]# cd redis-3.0.5
[root@web3 ~]# make && make install 

3.將redis-trib.rb 複製到/usr/local/bin

[root@web3 redis-3.0.5]# cd src/
[root@web3 src]# cp redis-trib.rb /usr/local/bin

4.開始集羣搭建

複製代碼
[root@web3 redis-3.0.5]# vi redis.conf
#修改如下地方
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
複製代碼

 

 
新建6個節點:
 
複製代碼
[root@web3 redis-3.0.5]# mkdir -p /usr/local/cluster-test
[root@web3 redis-3.0.5]# cd /usr/local/cluster-test/
[root@web3 cluster-test]# mkdir 7000
[root@web3 cluster-test]# mkdir 7001
[root@web3 cluster-test]# mkdir 7002
[root@web3 cluster-test]# mkdir 7003
[root@web3 cluster-test]# mkdir 7004
[root@web3 cluster-test]# mkdir 7005
複製代碼

將redis.conf 分別拷貝到這6個文件夾中,並修改爲對應的端口號

 
複製代碼
#拷貝配置文件
[root@web3 cluster-test]# cp /root/redis-3.0.5/redis.conf /usr/local/cluster-test/7000
[root@web3 cluster-test]# cp /root/redis-3.0.5/redis.conf /usr/local/cluster-test/7001
[root@web3 cluster-test]# cp /root/redis-3.0.5/redis.conf /usr/local/cluster-test/7002
[root@web3 cluster-test]# cp /root/redis-3.0.5/redis.conf /usr/local/cluster-test/7003
[root@web3 cluster-test]# cp /root/redis-3.0.5/redis.conf /usr/local/cluster-test/7004
[root@web3 cluster-test]# cp /root/redis-3.0.5/redis.conf /usr/local/cluster-test/7005
#修改端口號
root@web3 cluster-test]# sed -i "s/7000/7001/g" /usr/local/cluster-test/7001/redis.conf
[root@web3 cluster-test]# sed -i "s/7000/7002/g" /usr/local/cluster-test/7002/redis.conf
[root@web3 cluster-test]# sed -i "s/7000/7003/g" /usr/local/cluster-test/7003/redis.conf
[root@web3 cluster-test]# sed -i "s/7000/7004/g" /usr/local/cluster-test/7004/redis.conf
[root@web3 cluster-test]# sed -i "s/7000/7005/g" /usr/local/cluster-test/7005/redis.conf
複製代碼

分別,啓動這6個節點

複製代碼
[root@web3 cluster-test]# cd /usr/local/cluster-test/7000/
[root@web3 7000]# redis-server redis.conf
[root@web3 7000]# cd ../7001
[root@web3 7001]# redis-server redis.conf
[root@web3 7001]# cd ../7002
[root@web3 7002]# redis-server redis.conf
[root@web3 7002]# cd ../7003
[root@web3 7003]# redis-server redis.conf
[root@web3 7003]# cd ../7004
[root@web3 7004]# redis-server redis.conf
[root@web3 7004]# cd ../7005
[root@web3 7005]# redis-server redis.conf
[root@web3 7005]#
複製代碼

查看6個節點的啓動進程狀況:

 
複製代碼
[root@web3 7005]# ps -ef|grep redis
root 11380 1 0 07:37 ? 00:00:00 redis-server *:7000 [cluster]
root 11384 1 0 07:37 ? 00:00:00 redis-server *:7001 [cluster]
root 11388 1 0 07:37 ? 00:00:00 redis-server *:7002 [cluster]
root 11392 1 0 07:37 ? 00:00:00 redis-server *:7003 [cluster]
root 11396 1 0 07:37 ? 00:00:00 redis-server *:7004 [cluster]
root 11400 1 0 07:37 ? 00:00:00 redis-server *:7005 [cluster]
root 11404 8259 0 07:38 pts/0 00:00:00 grep redis
複製代碼

將6個節點連在一塊兒構招成集羣

須要用到的命令就是redis-trib.rb,這是官方的一個用ruby寫的一個操做redis cluster的命令,因此,你的機器上須要安裝ruby。咱們先試一下這個命令:

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

由於咱們要新建集羣, 因此這裏使用create命令. --replicas 1 參數表示爲每一個主節點建立一個從節點. 其餘參數是實例的地址集合。

因爲我機子上沒安裝ruby,因此,會報錯:

/usr/bin/env: ruby: No such file or directory

那先安裝ruby和rubygems: 

[root@web3 7005]# yum install ruby ruby-devel rubygems rpm-build

而後,再執行一次,發現仍是報錯:

[root@web3 7005]# 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
/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- redis (LoadError)
from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from /usr/local/bin/redis-trib.rb:25
[root@web3 7005]#
 原來是ruby和redis的鏈接沒安裝好:
 
[root@web3 7005]# gem install redis
Successfully installed redis-3.2.1
1 gem installed
Installing ri documentation for redis-3.2.1...
Installing RDoc documentation for redis-3.2.1...

好了。最重要的時刻來臨了,勝敗成舉在此了,啊啊啊啊啊啊,好激動:

 
複製代碼
[root@web3 7005]# 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
>>> Creating cluster
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7002: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7005: OK
>>> 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:7003 to 127.0.0.1:7000
Adding replica 127.0.0.1:7004 to 127.0.0.1:7001
Adding replica 127.0.0.1:7005 to 127.0.0.1:7002
M: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots:0-5460 (5461 slots) master
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
S: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
replicates 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
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: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots:0-5460 (5461 slots) master
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots: (0 slots) master
replicates 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4
M: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) master
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
M: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) master
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
複製代碼

 

哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈。終於他媽的成功了!!!!

Redis-trib會提示你作了什麼配置, 輸入yes接受. 集羣就被配置和加入了, 意思是, 實例會通過互相交流後啓動。

測試集羣的狀態:

 
複製代碼
[root@web3 7000]# redis-trib.rb check 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7002: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7004: OK
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots: (0 slots) slave
replicates 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
複製代碼

 

能夠看到有3個主節點,3個從節點。每一個節點都是成功的鏈接狀態。

3個主節點[M]是:

7000 (3707debcbe7be66d4a1968eaf3a5ffaf4308efa4) 
7001 (cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c) 
7002 (dfa0754c7854a874a6ebd2613b86140ad97701fc)

3個從節點[S]是:

7003 (d2237fdcfbba672de766b913d1186cebcb6e1761)->7000 
7004 (4b4aef8b48c427a3c903518339d53b6447c58b93)->7001 
7005 (30858dbf483b61b9838d5c1f853a60beaa4e7afd) ->7002

 

5. 測試鏈接集羣

剛纔集羣搭建成功了。按照redis cluster的特色,它是去中心化,每一個節點都是對等的,因此,你鏈接哪一個節點均可以獲取和設置數據,咱們來試一下。

redis-cli是redis默認的客戶端工具,啓動時加上`-c`參數,就能夠鏈接到集羣。

鏈接任意一個節點端口:

 
[root@web3 7000]# redis-cli -c -p 7000
127.0.0.1:7000>

設置一個值:

 
127.0.0.1:7000> set my_name yangyi
-> Redirected to slot [12803] located at 127.0.0.1:7002
OK
127.0.0.1:7002> get my_name
"yangyi"
127.0.0.1:7002>

前面理論知識咱們知道了,分配key的時候,它會使用CRC16('my_name')%16384算法,來計算,將這個key 放到哪一個節點,這裏分配到了12803slot 就分配到了7002(10923-16383)這個節點上。

Redirected to slot [12803] located at 127.0.0.1:7002

redis cluster 採用的方式很直接,它直接跳轉到7002 節點了,而不是還在自身的7000節點。

好,如今咱們鏈接7005這個節點:


[root@web3 7000]# redis-cli -c -p 7005
127.0.0.1:7005> get my_name
-> Redirected to slot [12803] located at 127.0.0.1:7002
"yangyi"
127.0.0.1:7002>

咱們一樣是獲取my_name的值,它一樣也是跳轉到了7002上。

咱們再嘗試一些其餘的能夠:

 
複製代碼
127.0.0.1:7002> set age 123
-> Redirected to slot [741] located at 127.0.0.1:7000
OK
127.0.0.1:7000> set height 565
-> Redirected to slot [8223] located at 127.0.0.1:7001
OK
127.0.0.1:7001> set sex 1
-> Redirected to slot [2584] located at 127.0.0.1:7000
OK
127.0.0.1:7000> set home china
-> Redirected to slot [10814] located at 127.0.0.1:7001
OK
127.0.0.1:7001> set city shanghai
-> Redirected to slot [11479] located at 127.0.0.1:7002
OK
127.0.0.1:7002> set citylocate shanghaipudong
OK
127.0.0.1:7001> set wsdwxzx hhh
-> Redirected to slot [15487] located at 127.0.0.1:7002
OK
127.0.0.1:7002> zadd erew 333 rrr
-> Redirected to slot [10576] located at 127.0.0.1:7001
(integer) 1
127.0.0.1:7000> zrange erew 0 -1
-> Redirected to slot [10576] located at 127.0.0.1:7001
1) "rrr"
127.0.0.1:7001>
複製代碼

能夠看出,數據都會在7000-7002 這3個主節點來跳轉存粗。

6. 測試集羣中的節點掛掉

上面咱們創建來了一個集羣。3個主節點[7000-7002]提供數據存粗和讀取,3個從節點[7003-7005]則是負責把[7000-7002]的數據同步到本身的節點上來,咱們來看一下[7003-7005]的appendonly.aof的內容。看看是否是不這樣:

 
複製代碼
[root@web3 7005]# cd /usr/local/cluster-test/7003
[root@web3 7003]# vi appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$3
age
$3
123
*3
$3
set
$3
sex
$1
1
*3
$3
set
$3
job
$3
php
複製代碼

咱們看下,的確是從7000節點上同步過來的數據,7004,7005也是。

下面,咱們先來模擬其中一臺Master主服務器掛掉的狀況,那就7000掛掉吧:

 
複製代碼
[root@web3 7003]# ps -ef|grep redis
root 11380 1 0 07:37 ? 00:00:03 redis-server *:7000 [cluster]
root 11384 1 0 07:37 ? 00:00:03 redis-server *:7001 [cluster]
root 11388 1 0 07:37 ? 00:00:03 redis-server *:7002 [cluster]
root 11392 1 0 07:37 ? 00:00:03 redis-server *:7003 [cluster]
root 11396 1 0 07:37 ? 00:00:04 redis-server *:7004 [cluster]
root 11400 1 0 07:37 ? 00:00:03 redis-server *:7005 [cluster]
[root@web3 7003]# kill 11380
[root@web3 7003]#
複製代碼

好,安裝前面的理論,7000主節點掛掉了,那麼這個時候,7000的從節點只有7003一個,確定7003就會被選舉稱Master節點了:

 
複製代碼
[root@web3 7003]# redis-trib.rb check 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: [ERR] Sorry, can't connect to node 127.0.0.1:7000
[root@web3 7003]# redis-trib.rb check 127.0.0.1:7001
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7002: OK
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots:0-5460 (5461 slots) master
0 additional replica(s)
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:10923-16383 (5461 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.
[root@web3 7003]#
複製代碼

看了下,上面有了三個M 節點了,果然,7003被選取成了替代7000成爲主節點了。那咱們來獲取原先存在7000節點的數據:

 
[root@web3 7003]# redis-cli -c -p 7001
127.0.0.1:7001> get sex
-> Redirected to slot [2584] located at 127.0.0.1:7003
"1"
127.0.0.1:7003>

數據果然沒有丟失,而是從7003上面獲取了。

OK。咱們再來模擬 7000節點從新啓動了的狀況,那麼它還會自動加入到集羣中嗎?那麼,7000這個節點上充當什麼角色呢? 咱們試一下:

從新啓動 7000 節點:

     
複製代碼
[root@web3 7003]# cd ../7000
[root@web3 7000]# ll
total 56
-rw-r--r-- 1 root root 114 Oct 17 08:16 appendonly.aof
-rw-r--r-- 1 root root 43 Oct 17 08:37 dump.rdb
-rw-r--r-- 1 root root 745 Oct 17 08:00 nodes.conf
-rw-r--r-- 1 root root 41550 Oct 17 07:37 redis.conf
[root@web3 7000]# redis-server redis.conf
複製代碼

 

     啓動好了,如今,再來檢查一下集羣:
 
複製代碼
redis-trib.rb check 127.0.0.1:700`
 
[root@web3 7000]# redis-trib.rb check 127.0.0.1:7001
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7002: OK
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots: (0 slots) slave
replicates d2237fdcfbba672de766b913d1186cebcb6e1761
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:10923-16383 (5461 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.
複製代碼

你看,7000節點啓動起來了,它卻做爲了 70003 的從節點了。驗證了以前的這張圖:

這裏寫圖片描述

必定要保證有3個master 節點,否則,集羣就掛掉了。

 

7. 集羣中新加入節點

咱們再來測試一下,新加入一個節點,分2種狀況,1是做爲主節點,2是做爲一個節點的從節點。咱們分別來試一下:

1. 新建一個 7006 節點 做爲一個新的主節點加入:

首先就是新建一個 7006的文件夾和redis.conf:

 
[root@web3 cluster-test]# cd /usr/local/cluster-test/
[root@web3 cluster-test]# mkdir 7006
[root@web3 cluster-test]# cp 7005/redis.conf 7006/redis.conf
#修改端口
[root@web3 cluster-test]sed -i "s/7005/7006/g" /usr/local/cluster-test/7006/redis.conf

啓動 7006 

複製代碼
[root@web3 7006]# redis-server redis.conf
[root@web3 7006]# ps -ef|grep redis
root 11384 1 0 07:37 ? 00:00:05 redis-server *:7001 [cluster]
root 11388 1 0 07:37 ? 00:00:05 redis-server *:7002 [cluster]
root 11392 1 0 07:37 ? 00:00:05 redis-server *:7003 [cluster]
root 11396 1 0 07:37 ? 00:00:06 redis-server *:7004 [cluster]
root 11400 1 0 07:37 ? 00:00:05 redis-server *:7005 [cluster]
root 12100 1 0 08:42 ? 00:00:01 redis-server *:7000 [cluster]
root 12132 1 0 09:09 ? 00:00:00 redis-server *:7006 [cluster]
root 12136 8259 0 09:10 pts/0 00:00:00 grep redis
複製代碼

ok,7006 端口已經啓動好了,而且進程也存在了,下面就是加入到集羣中,也是得用到redis-trib.rb命令:

redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000

add-node是加入指令,127.0.0.1:7006 表示新加入的節點,127.0.0.1:7000 表示加入的集羣的一個節點,用來辨識是哪一個集羣,理論上哪一個均可以。

 
複製代碼
[root@web3 7006]# redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000
>>> Adding node 127.0.0.1:7006 to cluster 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7002: OK
>>> Performing Cluster Check (using node 127.0.0.1:7000)
S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots: (0 slots) slave
replicates d2237fdcfbba672de766b913d1186cebcb6e1761
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:10923-16383 (5461 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.
Connecting to node 127.0.0.1:7006: OK
>>> Send CLUSTER MEET to node 127.0.0.1:7006 to make it join the cluster.
[OK] New node added correctly.
複製代碼
    
這個命令執行完成以後,它順便檢查來其餘的6個節點都是成功的,最後幾句話:
 
Connecting to node 127.0.0.1:7006: OK
>>> Send CLUSTER MEET to node 127.0.0.1:7006 to make it join the cluster.
[OK] New node added correctly.

表示新的節點鏈接成功了,並且也已經加入到集羣了,咱們再來檢查一下:

複製代碼
[root@web3 7006]# redis-trib.rb check 127.0.0.1:7006
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7002: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
>>> Performing Cluster Check (using node 127.0.0.1:7006)
M: efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006
slots: (0 slots) master
0 additional replica(s)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots: (0 slots) slave
replicates d2237fdcfbba672de766b913d1186cebcb6e1761
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots:0-5460 (5461 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.
複製代碼

 

 
能夠看到了,7006 已經成爲了主節點。

咱們也能夠鏈接到客戶端後,來看這個集羣節點狀況:

 
複製代碼
[root@web3 7006]# redis-cli -c -p 7006
127.0.0.1:7006> cluster nodes
cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001 master - 0 1445073797986 2 connected 5461-10922
4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004 slave cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 0 1445073799497 2 connected
efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006 myself,master - 0 0 0 connected
3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000 slave d2237fdcfbba672de766b913d1186cebcb6e1761 0 1445073797482 7 connected
dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002 master - 0 1445073798489 3 connected 10923-16383
30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005 slave dfa0754c7854a874a6ebd2613b86140ad97701fc 0 1445073798993 3 connected
d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003 master - 0 1445073799498 7 connected 0-5460
127.0.0.1:7006>
複製代碼

能夠看到 有7個節點。7006 也做爲了master節點,可是,可是,你看看後面的:

 
efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006
slots: (0 slots) master

臥槽,什麼狀況。o slots 也就是說,雖然它如今是主節點,可是,缺沒有分配任何節點給它,也就是它如今還不負責數據存取。那加上去有毛用啊!!!!

看來,redis cluster 不是在新加節點的時候幫咱們作好了遷移工做,須要咱們手動對集羣進行從新分片遷移,也是這個命令:

redis-trib.rb reshard 127.0.0.1:7000

這個命令是用來遷移slot節點的,後面的127.0.0.1:7000是表示是哪一個集羣,端口填[7000-7006]均可以,咱們運行下:

 
  1. 複製代碼
    [root@web3 7006]# redis-trib.rb reshard 127.0.0.1:7000
    Connecting to node 127.0.0.1:7006: OK
    Connecting to node 127.0.0.1:7001: OK
    Connecting to node 127.0.0.1:7004: OK
    Connecting to node 127.0.0.1:7000: OK
    Connecting to node 127.0.0.1:7002: OK
    Connecting to node 127.0.0.1:7005: OK
    Connecting to node 127.0.0.1:7003: OK
    >>> Performing Cluster Check (using node 127.0.0.1:7006)
    M: efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006
    slots: (0 slots) master
    0 additional replica(s)
    M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
    slots:5461-10922 (5462 slots) master
    1 additional replica(s)
    S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
    slots: (0 slots) slave
    replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
    S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
    slots: (0 slots) slave
    replicates d2237fdcfbba672de766b913d1186cebcb6e1761
    M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
    slots:10923-16383 (5461 slots) master
    1 additional replica(s)
    S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
    slots: (0 slots) slave
    replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
    M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
    slots:0-5460 (5461 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.
    How many slots do you want to move (from 1 to 16384)?
    複製代碼

它提示咱們須要遷移多少slot到7006上,咱們能夠算一下:16384/4 = 4096,也就是說,爲了平衡分配起見,咱們須要移動4096個槽點到7006上。

好,那輸入4096:

 
How many slots do you want to move (from 1 to 16384)? 4096
What is the receiving node ID?

它又提示咱們,接受的node ID是多少,7006的id 咱們經過上面就能夠看到是efc3131fbdc6cf929720e0e0f7136cae85657481 :

 
What is the receiving node ID? efc3131fbdc6cf929720e0e0f7136cae85657481
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1:

接着, redis-trib 會向你詢問從新分片的源節點(source node), 也便是, 要從哪一個節點中取出 4096 個哈希槽, 並將這些槽移動到7006節點上面。

若是咱們不打算從特定的節點上取出指定數量的哈希槽, 那麼能夠向 redis-trib 輸入 all , 這樣的話, 集羣中的全部主節點都會成爲源節點, redis-trib 將從各個源節點中各取出一部分哈希槽, 湊夠 4096 個, 而後移動到7006節點上:

 
Source node #1:all

接下來就開始遷移了,而且會詢問你是否確認:

複製代碼
Moving slot 1359 from d2237fdcfbba672de766b913d1186cebcb6e1761
Moving slot 1360 from d2237fdcfbba672de766b913d1186cebcb6e1761
Moving slot 1361 from d2237fdcfbba672de766b913d1186cebcb6e1761
Moving slot 1362 from d2237fdcfbba672de766b913d1186cebcb6e1761
Moving slot 1363 from d2237fdcfbba672de766b913d1186cebcb6e1761
Moving slot 1364 from d2237fdcfbba672de766b913d1186cebcb6e1761
Do you want to proceed with the proposed reshard plan (yes/no)?
複製代碼
輸入 yes 並使用按下回車以後, redis-trib 就會正式開始執行從新分片操做, 將指定的哈希槽從源節點一個個地移動到7006節點上面。

遷移完畢以後,咱們來檢查下:

 
複製代碼
[root@web3 7006]# redis-trib.rb check 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7002: OK
>>> Performing Cluster Check (using node 127.0.0.1:7000)
S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots: (0 slots) slave
replicates d2237fdcfbba672de766b913d1186cebcb6e1761
M: efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006
slots:0-1364,5461-6826,10923-12287 (4096 slots) master
0 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots:1365-5460 (4096 slots) master
1 additional replica(s)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:6827-10922 (4096 slots) master
1 additional replica(s)
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:12288-16383 (4096 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.
複製代碼

咱們着重看7006:

0-1364,5461-6826,10923-12287 (4096 slots)

這些原來在其餘節點上的slot 杯遷移到了7006上。原來,它只是間隔的移動,並非銜接的總體移動,咱們看下有數據了沒?

 
複製代碼
[root@web3 7006]# redis-cli -c -p 7006
127.0.0.1:7006> keys *
1) "city"
2) "age"
3) "citylocate"
127.0.0.1:7006> get city
"shanghai"
複製代碼

很是贊,已經有數據了。

 
2. 新建一個 7007從節點,做爲7006的從節點

咱們再新建一個節點7007,步驟相似,就先省略了。建好後,啓動起來,咱們看如何把它加入到集羣中的從節點中:

[root@web3 7007]# redis-trib.rb add-node --slave 127.0.0.1:7007 127.0.0.1:7000
的時候加上表示是加入到從節點中,可是這樣加,是隨機的。這裏的命令行徹底像咱們在添加一個新主服務器時使用的同樣,因此咱們沒有指定要給哪一個主服 務器添加副本。這種狀況下, 會將做爲一個具備較少副本的隨機的主服務器的副本。add-node--slaveredis-trib7007

那麼,你猜,它會做爲誰的從節點,應該是7006,由於7006尚未從節點。咱們運行下。

 
複製代碼
[root@web3 7007]# redis-trib.rb add-node --slave 127.0.0.1:7007 127.0.0.1:7000
...
...
[OK] All 16384 slots covered.
Automatically selected master 127.0.0.1:7006
Connecting to node 127.0.0.1:7007: OK
>>> Send CLUSTER MEET to node 127.0.0.1:7007 to make it join the cluster.
Waiting for the cluster to join.
>>> Configure node as replica of 127.0.0.1:7006.
[OK] New node added correctly.
複製代碼

上面提示說,自動選擇了7006做爲master節點。而且成功了。咱們檢查下:

 
複製代碼
[root@web3 7007]# redis-trib.rb check 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7007: OK
Connecting to node 127.0.0.1:7002: OK
>>> Performing Cluster Check (using node 127.0.0.1:7000)
S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots: (0 slots) slave
replicates d2237fdcfbba672de766b913d1186cebcb6e1761
M: efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006
slots:0-1364,5461-6826,10923-12287 (4096 slots) master
1 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots:1365-5460 (4096 slots) master
1 additional replica(s)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:6827-10922 (4096 slots) master
1 additional replica(s)
S: 86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007
slots: (0 slots) slave
replicates efc3131fbdc6cf929720e0e0f7136cae85657481
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:12288-16383 (4096 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.
複製代碼

果真,7007加入到了7006的從節點當中。

你說,我若是想指定一個主節點行不行?固然能夠。咱們再建一個7008節點。

 
複製代碼
redis-trib.rb add-node --slave --master-id efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7008 127.0.0.1:7000
--master-id 表示指定的主節點node id。這裏指定的是 7006 這個主節點。

 
Waiting for the cluster to join.
>>> Configure node as replica of 127.0.0.1:7006.
[OK] New node added correctly.
[root@web3 7008]#
複製代碼

提示咱們已經做爲7006的附屬品,也就是加入到7006的從節點來了,照這麼說,7006就有2個從節點了,咱們看一下:

 
redis-cli -c -p 7008 cluster nodes |grep efc3131fbdc6cf929720e0e0f7136cae85657481
86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007 slave efc3131fbdc6cf929720e0e0f7136cae85657481 0 1445089507786 8 connected
efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006 master - 0 1445089508289 8 connected 0-1364 5461-6826 10923-12287
44321e7d619410dc4e0a8745366610a0d06d2395 127.0.0.1:7008 myself,slave efc3131fbdc6cf929720e0e0f7136cae85657481 0 0 0 connected

咱們過濾了下看結果,果然,7007和7008是7006的從節點了。

恰好,咱們再作一個實驗,我把7006的殺掉,看7007和7008誰會變成主節點:

 
  1. 複製代碼
    [root@web3 7008]# ps -ef|grep redis
    root 11384 1 0 09:56 ? 00:00:16 redis-server *:7001 [cluster]
    root 11388 1 0 09:56 ? 00:00:16 redis-server *:7002 [cluster]
    root 11392 1 0 09:56 ? 00:00:16 redis-server *:7003 [cluster]
    root 11396 1 0 09:56 ? 00:00:15 redis-server *:7004 [cluster]
    root 11400 1 0 09:56 ? 00:00:15 redis-server *:7005 [cluster]
    root 12100 1 0 11:01 ? 00:00:11 redis-server *:7000 [cluster]
    root 12132 1 0 11:28 ? 00:00:11 redis-server *:7006 [cluster]
    root 12202 1 0 13:14 ? 00:00:02 redis-server *:7007 [cluster]
    root 12219 1 0 13:39 ? 00:00:00 redis-server *:7008 [cluster]
    root 12239 8259 0 13:49 pts/0 00:00:00 grep redis
    [root@web3 7008]# kill 12132
    [root@web3 7008]# redis-cli -c -p 7008
    127.0.0.1:7008> get ss5rtr
    -> Redirected to slot [1188] located at 127.0.0.1:7007
    "66"
    127.0.0.1:7007> cluster nodes
    efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006 master,fail - 1445089780668 1445089779963 8 disconnected
    d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003 master - 0 1445089812195 7 connected 1365-5460
    30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005 slave dfa0754c7854a874a6ebd2613b86140ad97701fc 0 1445089813710 3 connected
    86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007 myself,master - 0 0 10 connected 0-1364 5461-6826 10923-12287
    cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001 master - 0 1445089814214 2 connected 6827-10922
    4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004 slave cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 0 1445089812701 2 connected
    44321e7d619410dc4e0a8745366610a0d06d2395 127.0.0.1:7008 slave 86d05e7c2b197dc182b5e71069e791d033cf899e 0 1445089814214 10 connected
    3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000 slave d2237fdcfbba672de766b913d1186cebcb6e1761 0 1445089813204 7 connected
    dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002 master - 0 1445089813204 3 connected 12288-16383
    127.0.0.1:7007>
    複製代碼

     

看,7007得到了成爲主節點的機會,7008就變成了7007的從節點。

那麼這個時候,重啓7006節點,那麼他就會變成了一個7007的從節點了。

 
複製代碼
27.0.0.1:7008> cluster nodes
30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005 slave dfa0754c7854a874a6ebd2613b86140ad97701fc 0 1445089986148 3 connected
86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007 master - 0 1445089986652 10 connected 0-1364 5461-6826 10923-12287
d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003 master - 0 1445089986148 7 connected 1365-5460
cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001 master - 0 1445089987155 2 connected 6827-10922
efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006 slave 86d05e7c2b197dc182b5e71069e791d033cf899e 0 1445089985644 10 connected
44321e7d619410dc4e0a8745366610a0d06d2395 127.0.0.1:7008 myself,slave 86d05e7c2b197dc182b5e71069e791d033cf899e 0 0 0 connected
dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002 master - 0 1445089986652 3 connected 12288-16383
4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004 slave cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 0 1445089987660 2 connected
3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000 slave d2237fdcfbba672de766b913d1186cebcb6e1761 0 1445089985644 7 connected
127.0.0.1:7008>
複製代碼
3. 移除一個主節點

有加確定有減,redis cluster一樣支持移除節點功能,一樣也是redis-trib.rb的用法:

redis-trib del-node 127.0.0.1:7000 `<node-id>`

和新加節點有點不一樣的是,移除須要節點的node-id。那咱們嘗試將7007這個主節點移除:

 
複製代碼
[root@web3 7006]# redis-trib.rb del-node 127.0.0.1:7000 86d05e7c2b197dc182b5e71069e791d033cf899e
>>> Removing node 86d05e7c2b197dc182b5e71069e791d033cf899e from cluster 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7007: OK
Connecting to node 127.0.0.1:7008: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7002: OK
[ERR] Node 127.0.0.1:7007 is not empty! Reshard data away and try again.
複製代碼

報錯了,它提示咱們說,因爲7007裏面已經有數據了,不能被移除,要先將它的數據轉移出去。也就是說得從新分片,用上面增長新節點後的分片方式同樣,用咱們再來一遍:

redis-trib.rb reshard 127.0.0.1:7000

因爲中間太多內容,就省略不重要的,只簡單說明下關鍵的幾步:

 
M: 86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007
slots:0-1364,5461-6826,10923-12287 (4096 slots) master
How many slots do you want to move (from 1 to 16384)?

提示,咱們要分多少個槽點,因爲7007上有4096個槽點,因此這裏填寫4096

 
How many slots do you want to move (from 1 to 16384)? 4096
What is the receiving node ID?

提示咱們,須要移動到哪一個id上,那就填7001的吧:

 
What is the receiving node ID? cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1:

這裏就是關鍵了,它要咱們從哪一個節點去轉移數據到7001,由於咱們是要刪除7007的,因此,咱們就得7007的id了

 
Source node #1:86d05e7c2b197dc182b5e71069e791d033cf899e
Source node #2:done
Do you want to proceed with the proposed reshard plan (yes/no)? yes

ok,這樣就遷移好了。咱們看看7007是否爲空了:

 
[root@web3 7006]# redis-cli -c -p 7007
127.0.0.1:7007> keys *
(empty list or set)
127.0.0.1:7007> cluster nodes
86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007 myself,master - 0 0 10 connected

果真爲空了,好。如今再進行移除節點操做:

 
複製代碼
[root@web3 7006]# redis-trib.rb del-node 127.0.0.1:7000 86d05e7c2b197dc182b5e71069e791d033cf899e
>>> Removing node 86d05e7c2b197dc182b5e71069e791d033cf899e from cluster 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7007: OK
Connecting to node 127.0.0.1:7008: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7002: OK
>>> Sending CLUSTER FORGET messages to the cluster...
>>> 127.0.0.1:7006 as replica of 127.0.0.1:7001
>>> 127.0.0.1:7008 as replica of 127.0.0.1:7001
>>> SHUTDOWN the node.
複製代碼

哈哈哈哈哈,刪除成功,並且還很人性化的將700670082個沒了爹的孩子送給了7001。好評👌

咱們再檢查一下:7007 已經移除,連不上了。

 
複製代碼
[root@web3 7006]# redis-trib.rb check 127.0.0.1:7007
Connecting to node 127.0.0.1:7007: [ERR] Sorry, can't connect to node 127.0.0.1:7007
 
[root@web3 7006]# redis-trib.rb check 127.0.0.1:7008
Connecting to node 127.0.0.1:7008: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7002: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7000: OK
>>> Performing Cluster Check (using node 127.0.0.1:7008)
S: 44321e7d619410dc4e0a8745366610a0d06d2395 127.0.0.1:7008
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots:1365-5460 (4096 slots) master
1 additional replica(s)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:0-1364,5461-12287 (8192 slots) master
3 additional replica(s)
S: efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:12288-16383 (4096 slots) master
1 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots: (0 slots) slave
replicates d2237fdcfbba672de766b913d1186cebcb6e1761
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@web3 7006]#
複製代碼

70067008果真也成功加入到了7001的你們庭。

 
4. 移除一個從節點

移除一個從節點就簡單的多了,由於不須要考慮數據的遷移,咱們7008給移除:

 
複製代碼
[root@web3 7006]# redis-trib.rb del-node 127.0.0.1:7005 44321e7d619410dc4e0a8745366610a0d06d2395
>>> Removing node 44321e7d619410dc4e0a8745366610a0d06d2395 from cluster 127.0.0.1:7005
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7002: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7008: OK
Connecting to node 127.0.0.1:7003: OK
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
[root@web3 7006]# redis-trib.rb check 127.0.0.1:7008
Connecting to node 127.0.0.1:7008: [ERR] Sorry, can't connect to node 127.0.0.1:7008
複製代碼

 

移除成功。

 

redis單例、主從模式、sentinel以及集羣的配置方式及優缺點對比 

 

張旭峯
  張旭峯 發佈於 2017/05/21 01:32
 
字數 5452
 
閱讀 3540
 
收藏  140
 
點贊  7
 
 評論 9
 

      redis做爲一種高效的緩存框架,使用是很是普遍的,在數據存儲上,在運行時其將數據存儲在內存中,以實現數據的高效讀寫,而且根據定製的持久化規則不一樣,其會不按期的將數據持久化到硬盤中。另外相較於其餘的NoSql數據庫,redis提供了很是豐富的數據結構,如dict,sds,linkedlist,ziplist,set,quicklist,geometry。在這些存儲結構的基礎上,redis爲用戶提供了很是豐富的操做選擇,如經過zskiplist來達到對某種類型的數據的排序目的,而排序在數據庫中是一個很是耗時的操做。

1.redis單例的安裝和使用

      redis相對於其餘的緩存框架安裝很是的方便,只須要從https://redis.io/download下載後解壓,進入redis目錄以後執行以下命令即安裝完成:

make install

這裏須要注意的是make是gcc中的一個命令,安裝以前請確保機器安裝了gcc。redis中全部的命令都在redis安裝目錄中的src子目錄下,其中比較重要的是redis-server,redis-sentinel,redis-cli。

      編譯完成以後在src目錄下執行./redis-server啓動redis(啓動後可關閉該窗口),而後新開一個窗口,在命令行中執行./redis-cli便可鏈接啓動的redis服務。在其中執行以下命令便可看到編譯安裝成功了:

127.0.0.1:6379> set hello world OK 127.0.0.1:6379> get hello "world"

      這裏須要說明的是,按照上述方式啓動redis,其使用的ip爲本機ip 127.0.0.1,端口爲6379,而且其他的配置採用的都是默認配置,相關配置可在redis安裝目錄下的redis.conf文件中查看。若是須要按照指定的配置文件來啓動,可在redis-server後接上配置文件名,如:

./src/redis-server redis.conf

另外,上述使用redis-cli鏈接redis客戶端時若是不帶任何參數,那麼其鏈接的默認ip和端口爲127.0.0.1:6379。若是須要鏈接指定ip和端口的客戶端,可使用以下方式:

./src/redis-cli -h 127.0.0.1 -p 6379

這裏-h參數表示鏈接的ip,-p則表示鏈接的端口。

      配置好redis以後,咱們就能夠在redis中執行相關命令來操做數據,關於redis的經常使用命令,可查看本人的另外一篇博客《redis經常使用命令大全》,其中有比較詳細的講解。

2.redis主從模式的配置

      redis單例提供了一種數據緩存方式和豐富的數據操做api,可是將數據徹底存儲在單個redis中主要存在兩個問題:數據備份和數據體量較大形成的性能下降。這裏redis的主從模式爲這兩個問題提供了一個較好的解決方案。主從模式指的是使用一個redis實例做爲主機,其他的實例做爲備份機。主機和從機的數據徹底一致,主機支持數據的寫入和讀取等各項操做,而從機則只支持與主機數據的同步和讀取,也就是說,客戶端能夠將數據寫入到主機,由主機自動將數據的寫入操做同步到從機。主從模式很好的解決了數據備份問題,而且因爲主從服務數據幾乎是一致的,於是能夠將寫入數據的命令發送給主機執行,而讀取數據的命令發送給不一樣的從機執行,從而達到讀寫分離的目的。以下所示主機redis-A分別有redis-B、redis-C、redis-D、redis-E四個從機:

      前面第1點中咱們已經介紹了redis單例的配置方式,而上面咱們也介紹了主從模式其實也是多個redis實例組成的,於是redis主從模式的配置能夠理解爲多個不一樣的redis實例經過必定的配置告知其相互之間的主從關係。而前面已經介紹,每一個redis實例都會佔用一個本機的端口號,主從模式的配置主要的配置點有兩個:當前實例端口號和當前實例是主機仍是從機,是從機的話其主機的ip和端口是什麼。通常的redis目錄下的redis.conf保存的是默認配置,儘可能不要對其進行修改,這裏咱們複製三份redis.conf文件,分別命名爲6379.conf,6380.conf和6381.conf,以下是端口爲6379的主機的主要配置:

bind 127.0.0.1 port 6379 logfile "6379.log" dbfilename "dump-6379.rdb"

以下是端口爲6380和6381的從機的配置:

bind 127.0.0.1 port 6380 logfile "6380.log" dbfilename "dump-6380.rdb" slaveof 127.0.0.1 6379
bind 127.0.0.1 port 6381 logfile "6381.log" dbfilename "dump-6381.rdb" slaveof 127.0.0.1 6379

      能夠看到,端口爲6380和6381的實例被配置爲端口爲6379的實例的從機。配置完成後使用redis-server分別執行以下命令啓動三個實例:

./src/redis-server 6379.conf ./src/redis-server 6380.conf ./src/redis-server 6381.conf

啓動以後分別開啓開啓三個命令行工具分別執行如下命令鏈接redis實例:

./src/redis-cli -p 6379 ./src/redis-cli -p 6380 ./src/redis-cli -p 6381

分別在三個命令行工具中執行一個get命令,獲取鍵名爲msg的數據,以下所示:

127.0.0.1:6379> get msg (nil)
127.0.0.1:6380> get msg (nil)
127.0.0.1:6381> get msg (nil)

能夠看到,在三個redis實例中都不存在鍵爲msg的數據,如今咱們在主機6379上設置一個鍵爲msg的數據,以下所示:

127.0.0.1:6379> set msg "hello" OK

能夠看到設置成功了,此時咱們在6380和6381的實例上執行get msg的命令,以下所示:

127.0.0.1:6380> get msg "hello"
127.0.0.1:6381> get msg "hello"

能夠看到,雖然咱們只是在6379的實例上設置了msg這條數據,可是在6380和6381的實例上也存有了相應的數據,說明咱們成功配置了redis的主從模式。另外,若是不在配置文件中指定主從節點的關係,也能夠在啓動相關redis實例以後使用slaveof命令來指定當前節點稱爲某個節點的從節點,如:

127.0.0.1:6380> slaveof 127.0.0.1 6379

3.redis中sentinel配置

      redis主從模式解決了數據備份和單例可能存在的性能問題,可是其也引入了新的問題。因爲主從模式配置了三個redis實例,而且每一個實例都使用不一樣的ip(若是在不一樣的機器上)和端口號,根據前面所述,主從模式下能夠將讀寫操做分配給不一樣的實例進行從而達到提升系統吞吐量的目的,但也正是由於這種方式形成了使用上的不便,由於每一個客戶端鏈接redis實例的時候都是指定了ip和端口號的,若是所鏈接的redis實例由於故障下線了,而主從模式也沒有提供必定的手段通知客戶端另外可鏈接的客戶端地址,於是須要手動更改客戶端配置從新鏈接。另外,主從模式下,若是主節點因爲故障下線了,那麼從節點由於沒有主節點而同步中斷,於是須要人工進行故障轉移工做。

      爲了解決這兩個問題,在2.8版本以後redis正式提供了sentinel(哨兵)架構。關於sentinel,這裏須要說明幾個概念:

名詞 邏輯結構 物理結構
主節點 redis主服務/數據庫 一個獨立的redis進程
從節點 redis從服務/數據庫 一個獨立的redis進程
sentinel節點 監控redis數據節點 一個獨立的sentinel進程
sentinel節點集合 若干sentinel節點的抽象集合 若干sentinel節點進程
應用方 泛指一個或多個客戶端 一個或多個客戶端線程或進程

      每一個sentinel節點其實就是一個redis實例,與主從節點不一樣的是sentinel節點做用是用於監控redis數據節點的,而sentinel節點集合則表示監控一組主從redis實例多個sentinel監控節點的集合,好比有主節點master和從節點slave-一、slave-2,爲了監控這三個主從節點,這裏配置N個sentinel節點sentinel-1,sentinel-2,...,sentinel-N。以下圖是sentinel監控主從節點的示例圖:

      從圖中能夠看出,對於一組主從節點,sentinel只是在其外部額外添加的一組用於監控做用的redis實例。在主從節點和sentinel節點集合配置好以後,sentinel節點之間會相互發送消息,以檢測其他sentinel節點是否正常工做,而且sentinel節點也會向主從節點發送消息,以檢測監控的主從節點是否正常工做。。前面講到,sentinel架構的主要做用是解決主從模式下主節點的故障轉移工做的。這裏若是主節點由於故障下線,那麼某個sentinel節點發送檢測消息給主節點時,若是在指定時間內收不到回覆,那麼該sentinel就會主觀的判斷該主節點已經下線,那麼其會發送消息給其他的sentinel節點,詢問其是否「認爲」該主節點已下線,其他的sentinel收到消息後也會發送檢測消息給主節點,若是其認爲該主節點已經下線,那麼其會回覆向其詢問的sentinel節點,告知其也認爲主節點已經下線,當該sentinel節點最早收到超過指定數目(配置文件中配置的數目和當前sentinel節點集合數的一半,這裏兩個數目的較大值)的sentinel節點回復說當前主節點已下線,那麼其就會對主節點進行故障轉移工做,故障轉移的基本思路是在從節點中選取某個從節點向其發送slaveof no one(假設選取的從節點爲127.0.0.1:6380),使其稱爲獨立的節點(也就是新的主節點),而後sentinel向其他的從節點發送slaveof 127.0.0.1 6380命令使它們從新成爲新的主節點的從節點。從新分配以後sentinel節點集合還會繼續監控已經下線的主節點(假設爲127.0.0.1:6379),若是其從新上線,那麼sentinel會向其發送slaveof命令,使其成爲新的主機點的從節點,如此故障轉移工做完成。

      上面咱們講到了,每一個sentinel節點在本質上仍是一個redis實例,只不過和redis數據節點不一樣的是,其主要做用是監控redis數據節點。在redis安裝目錄下有個默認的sentinel配置文件sentinel.conf,和配置主從節點相似,這裏複製三個配置文件:sentinel-26379.conf,sentinel-26380.conf和sentinel-26381.conf。分別按照以下示例編輯這三個配置文件:

port 26379 daemonize yes logfile "26379.log" dir /opt/soft/redis/data sentinel monitor mymaster 127.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 30000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 sentinel myid mm55d2d712b1f3f312b637f9b546f00cdcedc787

對於端口爲26380和26381的sentinel,其配置和上述相似,只須要把相應的端口號修改成對應的端口號便可。這裏注意兩點:①每一個sentinel的myid參數也要進行修改,由於sentinel之間是經過該屬性來惟一區分其餘sentinel節點的;②參數中sentinel monitor mymaster 127.0.0.1 6379 2這裏的端口號6379是不用更改的,由於sentinel是經過檢測主節點的狀態來得知當前主節點的從節點有哪些的,於是設置爲主節點的端口號便可。配置完成後咱們首先啓動三個主從節點,而後分別使用三個配置文件使用以下命令啓用sentinel:

./src/redis-sentinel sentinel-26379.conf ./src/redis-sentinel sentinel-26380.conf ./src/redis-sentinel sentinel-26381.conf

因爲sentinel節點也是一個redis實例,於是咱們能夠經過以下命令使用redis-cli鏈接sentinel節點:

./src/redis-cli -p 26379

連上sentinel節點以後咱們能夠經過以下命令查看sentinel狀態:

127.0.0.1:26379> 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:6379,slaves=2,sentinels=3

能夠看到,sentinel檢測到主從節點總共有三個,其中一個主節點,兩個從節點,而且sentinel節點總共也有三個。啓動完成以後,咱們能夠經過主動下線主節點來模擬sentinel的故障轉移過程。首先咱們鏈接上端口爲6379的主節點,使用以下命令查看主從節點狀態:

127.0.0.1:6379> info replication

結果以下:

# Replication
role:master
connected_slaves:2 slave0:ip=127.0.0.1,port=6380,state=online,offset=45616,lag=1 slave1:ip=127.0.0.1,port=6381,state=online,offset=45616,lag=1 master_repl_offset:45616 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:45615

能夠看到,當前主節點有兩個從節點,端口分別爲6380和6381。而後咱們對主節點執行以下命令:

127.0.0.1:6379> shutdown save

而後咱們鏈接上端口號爲6380的從節點,並執行以下命令:

127.0.0.1:6380> info replication 

結果以下:

# Replication
role:master
connected_slaves:1 slave0:ip=127.0.0.1,port=6381,state=online,offset=12344,lag=0 master_repl_offset:12477 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:12476

能夠看到,當端口爲6379的實例下線以後,端口爲6380的實例被從新競選爲新的主節點,而且端口爲6381的實例被設置爲6380的實例的從節點。若是咱們此時從新啓用端口爲6379的節點,而後再查看主從狀態,結果以下:

# Replication
role:master
connected_slaves:2 slave0:ip=127.0.0.1,port=6381,state=online,offset=59918,lag=0 slave1:ip=127.0.0.1,port=6379,state=online,offset=59918,lag=1 master_repl_offset:60051 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:60050

能夠看到,端口爲6379的redis實例從新鏈接後,sentinel節點檢測到其從新鏈接,那麼對其發送命令,使其成爲新的主節點的從節點。

4.redis集羣的配置

      redis集羣是在redis 3.0版本推出的一個功能,其有效的解決了redis在分佈式方面的需求。當遇到單機內存,併發和流量瓶頸等問題時,可採用Cluster方案達到負載均衡的目的。而且從另外一方面講,redis中sentinel有效的解決了故障轉移的問題,也解決了主節點下線客戶端沒法識別新的可用節點的問題,可是若是是從節點下線了,sentinel是不會對其進行故障轉移的,而且鏈接從節點的客戶端也沒法獲取到新的可用從節點,而這些問題在Cluster中都獲得了有效的解決。

      redis集羣中數據是和槽(slot)掛鉤的,其總共定義了16384個槽,全部的數據根據一致哈希算法會被映射到這16384個槽中的某個槽中;另外一方面,這16384個槽是按照設置被分配到不一樣的redis節點上的,好比啓動了三個redis實例:cluster-A,cluster-B和cluster-C,這裏將0-5460號槽分配給cluster-A,將5461-10922號槽分配給cluster-B,將10923-16383號槽分配給cluster-C(總共有16384個槽,可是其標號相似數組下標,是從0到16383)。也就是說數據的存儲只和槽有關,而且槽的數量是必定的,因爲一致hash算法是必定的,於是將這16384個槽分配給不管多少個redis實例,對於確認的數據其都將被分配到肯定的槽位上。redis集羣經過這種方式來達到redis的高效和高可用性目的。

      這裏須要進行說明的一點是,一致哈希算法根據數據的key值計算映射位置時和所使用的節點數量有很是大的關係。一致哈希分區的實現思路是爲系統中每一個節點分配一個token,範圍通常在0~2^32,這些token構成一個哈希環,數據讀寫執行節點查找操做時,先根據key計算hash值,而後順時針找到第一個大於等於該hash值的token節點,須要操做的數據就保存在該節點上。經過分析能夠發現,一致哈希分區存在以下問題:

  1. 加減節點會形成哈希環中部分數據沒法命中,須要手動處理或忽略這部分數據;
  2. 當使用少許節點時,節點變化將大範圍影響環中數據映射,所以這種方式不適合少許節點的分佈式方案;
  3. 普通的一致性哈希分區在增減節點時須要增長一倍或減去一半節點才能保證數據和負載的平衡。

正是因爲一致哈希分區的這些問題,redis使用了虛擬槽來處理分區時節點變化的問題,也即將全部的數據映射到16384個虛擬槽位上,當redis節點變化時數據映射的槽位將不會變化,而且這也是redis進行節點擴張的基礎。

      對於redis集羣的配置,首先將redis安裝目錄下的redis.conf文件複製六份,分別取名爲:cluster-6379.conf、cluster-6380.conf、cluster-6381.conf、cluster-6382.conf、cluster-6383.conf、cluster-6384.conf。對於一個高可用的集羣方案,集羣每一個節點都將爲其分配一個從節點,以防止數據節點由於故障下線,這裏使用六份配置文件定義六個redis實例,其中三個做爲主節點,剩餘三個分別做爲其從節點。對於這六份配置文件,以其中一份爲例,如下是其須要修改的參數:

port 6379 cluster-enabled yes cluster-node-timeout 15000 cluster-config-file "nodes-6379.conf" pidfile /var/run/redis_6379.pid logfile "cluster-6379.log" dbfilename dump-cluster-6379.rdb appendfilename "appendonly-cluster-6379.aof"

對於其他的配置文件,只須要將其中對應項的端口號和帶有端口號的文件名修改成當前要指定的端口號和端口號的文件名便可。配置文件配置好以後使用以下命令啓動集羣中的每一個實例:

./src/redis-server cluster-6379.conf ./src/redis-server cluster-6380.conf ./src/redis-server cluster-6381.conf ./src/redis-server cluster-6382.conf ./src/redis-server cluster-6383.conf ./src/redis-server cluster-6384.conf

仔細閱讀上述配置文件可發現,當前配置和啓動過程當中並無指定這六個實例的主從關係,也沒有對16384個槽位進行分配。於是咱們還須要進行進一步的配置,槽位的分配和主從關係的設定有兩種方式進行,一種是使用redis-cli鏈接到集羣節點上後使用cluster meet命令鏈接其餘的節點,如咱們首先執行以下命令鏈接到6379端口的節點:

./src/redis-cli -p 6379

鏈接上後使用cluster meet命令分別鏈接其他節點:

127.0.0.1:6379>cluster meet 127.0.0.1 6380 127.0.0.1:6379>cluster meet 127.0.0.1 6381 127.0.0.1:6379>cluster meet 127.0.0.1 6382 127.0.0.1:6379>cluster meet 127.0.0.1 6383 127.0.0.1:6379>cluster meet 127.0.0.1 6384 

鏈接好後可使用cluster nodes命令查看當前集羣狀態:

127.0.0.1:6379> cluster nodes 4fa7eac4080f0b667ffeab9b87841da49b84a6e4 127.0.0.1:6384 master - 0 1468073975551 5 connected cfb28ef1deee4e0fa78da86abe5d24566744411e 127.0.0.1:6379 myself,master - 0 0 0 connected be9485a6a729fc98c5151374bc30277e89a461d8 127.0.0.1:6383 master - 0 1468073978579 4 connected 40622f9e7adc8ebd77fca0de9edfe691cb8a74fb 127.0.0.1:6382 master - 0 1468073980598 3 connected 8e41673d59c9568aa9d29fb174ce733345b3e8f1 127.0.0.1:6380 master - 0 1468073974541 1 connected 40b8d09d44294d2e23c7c768efc8fcd153446746 127.0.0.1:6381 master - 0 1468073979589 2 connected

能夠看到配置的六個節點都已經加入到了集羣中,可是其如今還不能使用,由於尚未將16384個槽分配到集羣節點中。虛擬槽的分配可使用redis-cli分別鏈接到6379,6380和6381端口的節點中,而後分別執行以下命令:

127.0.0.1:6379>cluster addslots {0...5461}
127.0.0.1:6380>cluster addslots {5462...10922}
127.0.0.1:6381>cluster addslots {10923...16383}

添加完槽位後可以使用cluster info命令查看當前集羣狀態:

127.0.0.1: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:5 cluster_my_epoch:0 cluster_stats_messages_sent:4874 cluster_stats_messages_received:4726 

這裏咱們將16384個虛擬槽位分配給了三個節點,而剩餘的三個節點咱們經過以下命令將其配置爲這三個節點的從節點,從而達到高可用的目的:

127.0.0.1:6382>cluster replicate cfb28ef1deee4e0fa78da86abe5d24566744411e OK 127.0.0.1:6383>cluster replicate 8e41673d59c9568aa9d29fb174ce733345b3e8f1 OK 127.0.0.1:6384>cluster replicate 40b8d09d44294d2e23c7c768efc8fcd153446746 OK 

如此,全部的集羣節點都配置完畢,而且處於可用狀態。這裏可使用cluster nodes命令查看當前節點的狀態:

127.0.0.1:6379> cluster nodes 4fa7eac4080f0b667ffeab9b87841da49b84a6e4 127.0.0.1:6384 slave 40b8d09d44294d2e23c7c768efc8fcd153446746 0 1468076865939 5 connected cfb28ef1deee4e0fa78da86abe5d24566744411e 127.0.0.1:6379 myself,master - 0 0 0 connected 0-5461 be9485a6a729fc98c5151374bc30277e89a461d8 127.0.0.1:6383 slave 8e41673d59c9568aa9d29fb174ce733345b3e8f1 0 1468076868966 4 connected 40622f9e7adc8ebd77fca0de9edfe691cb8a74fb 127.0.0.1:6382 slave cfb28ef1deee4e0fa78da86abe5d24566744411e 0 1468076869976 3 connected 8e41673d59c9568aa9d29fb174ce733345b3e8f1 127.0.0.1:6380 master - 0 1468076870987 1 connected 5462-10922 40b8d09d44294d2e23c7c768efc8fcd153446746 127.0.0.1:6381 master - 0 1468076867957 2 connected 10923-16383

咱們使用redis-cli使用以下命令鏈接集羣:

./src/redis-cli -c -p 6380

注意鏈接集羣模式的redis實例時須要加上參數-c,表示鏈接的是集羣模式的實例。鏈接上後執行get命令:

127.0.0.1:6380> get hello -> Redirected to slot [866] located at 127.0.0.1:6379 (nil)

能夠看到,在6380端口的實例上執行get命令時,其首先會爲當前的鍵經過一致哈希算法計算其所在的槽位,而且判斷該槽位不在當前redis實例中,於是重定向到目標實例上執行該命令,最後發現沒有該鍵對應的值,於是返回了一個(nil)。

相關文章
相關標籤/搜索