本文參考:Redis Cluster集群的搭建與實(shí)踐
redis最開始使用主從模式做集群咽斧,若master宕機(jī)需要手動配置slave轉(zhuǎn)為master娜饵;后來為了高可用提出來哨兵模式柔逼,該模式下有一個哨兵監(jiān)視master和slave盯腌,若master宕機(jī)可自動將slave轉(zhuǎn)為master冻辩,但它也有一個問題蛋铆,就是不能動態(tài)擴(kuò)充驱显;所以在3.x提出cluster集群模式诗芜。
一、redis-cluster設(shè)計
Redis-Cluster采用無中心結(jié)構(gòu)埃疫,每個節(jié)點(diǎn)保存數(shù)據(jù)和整個集群狀態(tài),每個節(jié)點(diǎn)都和其他所有節(jié)點(diǎn)連接伏恐。
其結(jié)構(gòu)特點(diǎn):
1、所有的redis節(jié)點(diǎn)彼此互聯(lián)(PING-PONG機(jī)制),內(nèi)部使用二進(jìn)制協(xié)議優(yōu)化傳輸速度和帶寬栓霜。
2翠桦、節(jié)點(diǎn)的fail是通過集群中超過半數(shù)的節(jié)點(diǎn)檢測失效時才生效。
3胳蛮、客戶端與redis節(jié)點(diǎn)直連,不需要中間proxy層.客戶端不需要連接集群所有節(jié)點(diǎn),連接集群中任何一個可用節(jié)點(diǎn)即可销凑。
4、redis-cluster把所有的物理節(jié)點(diǎn)映射到[0-16383]slot上(不一定是平均分配),cluster 負(fù)責(zé)維護(hù)node<->slot<->value仅炊。
5斗幼、Redis集群預(yù)分好16384個桶,當(dāng)需要在 Redis 集群中放置一個 key-value 時抚垄,根據(jù) CRC16(key) mod 16384的值蜕窿,決定將一個key放到哪個桶中。
a.redis cluster節(jié)點(diǎn)分配
現(xiàn)在我們是三個主節(jié)點(diǎn)分別是:A, B, C 三個節(jié)點(diǎn)呆馁,它們可以是一臺機(jī)器上的三個端口桐经,也可以是三臺不同的服務(wù)器。那么浙滤,采用哈希槽 (hash slot)的方式來分配16384個slot 的話阴挣,它們?nèi)齻€節(jié)點(diǎn)分別承擔(dān)的slot 區(qū)間是:
節(jié)點(diǎn)A覆蓋0-5460;
節(jié)點(diǎn)B覆蓋5461-10922;
-
節(jié)點(diǎn)C覆蓋10923-16383.
獲取數(shù)據(jù):
如果存入一個值,按照redis cluster哈希槽的算法: CRC16('key')384 = 6782瓷叫。 那么就會把這個key 的存儲分配到 B 上了屯吊。同樣送巡,當(dāng)我連接(A,B,C)任何一個節(jié)點(diǎn)想獲取'key'這個key時,也會這樣的算法盒卸,然后內(nèi)部跳轉(zhuǎn)到B節(jié)點(diǎn)上獲取數(shù)據(jù)新增一個主節(jié)點(diǎn):
新增一個節(jié)點(diǎn)D骗爆,redis cluster的這種做法是從各個節(jié)點(diǎn)的前面各拿取一部分slot到D上,我會在接下來的實(shí)踐中實(shí)驗蔽介。大致就會變成這樣: 節(jié)點(diǎn)A覆蓋1365-5460
節(jié)點(diǎn)B覆蓋6827-10922
節(jié)點(diǎn)C覆蓋12288-16383
節(jié)點(diǎn)D覆蓋0-1364,5461-6826,10923-12287
同樣刪除一個節(jié)點(diǎn)也是類似摘投,移動完成后就可以刪除這個節(jié)點(diǎn)了。
b.Redis Cluster主從模式
redis cluster 為了保證數(shù)據(jù)的高可用性虹蓄,加入了主從模式犀呼,一個主節(jié)點(diǎn)對應(yīng)一個或多個從節(jié)點(diǎn),主節(jié)點(diǎn)提供數(shù)據(jù)存取薇组,從節(jié)點(diǎn)則是從主節(jié)點(diǎn)拉取數(shù)據(jù)備份外臂,當(dāng)這個主節(jié)點(diǎn)掛掉后,就會有這個從節(jié)點(diǎn)選取一個來充當(dāng)主節(jié)點(diǎn)律胀,從而保證集群不會掛掉
上面那個例子里, 集群有ABC三個主節(jié)點(diǎn), 如果這3個節(jié)點(diǎn)都沒有加入從節(jié)點(diǎn)宋光,如果B掛掉了,我們就無法訪問整個集群了炭菌。A和C的slot也無法訪問罪佳。
所以我們在集群建立的時候,一定要為每個主節(jié)點(diǎn)都添加了從節(jié)點(diǎn), 比如像這樣, 集群包含主節(jié)點(diǎn)A黑低、B赘艳、C, 以及從節(jié)點(diǎn)A1、B1克握、C1, 那么即使B掛掉系統(tǒng)也可以繼續(xù)正確工作蕾管。
B1節(jié)點(diǎn)替代了B節(jié)點(diǎn),所以Redis集群將會選擇B1節(jié)點(diǎn)作為新的主節(jié)點(diǎn)玛荞,集群將會繼續(xù)正確地提供服務(wù)娇掏。 當(dāng)B重新開啟后呕寝,它就會變成B1的從節(jié)點(diǎn)勋眯。
不過需要注意,如果節(jié)點(diǎn)B和B1同時掛了下梢,Redis集群就無法繼續(xù)正確地提供服務(wù)了客蹋。
二、redis集群的搭建
集群中至少應(yīng)該有奇數(shù)個節(jié)點(diǎn)孽江,所以至少有三個節(jié)點(diǎn)讶坯,每個節(jié)點(diǎn)至少有一個備份節(jié)點(diǎn),所以下面使用6節(jié)點(diǎn)(主節(jié)點(diǎn)岗屏、備份節(jié)點(diǎn)由redis-cluster集群確定)
下載redis
1辆琅、安裝redis節(jié)點(diǎn)指定端口
解壓redis壓縮包漱办,編譯安裝
[root@localhost redis-3.2.0]# tar xzf redis-3.2.0.tar.gz
[root@localhost redis-3.2.0]# cd redis-3.2.0
[root@localhost redis-3.2.0]# make
[root@localhost redis01]# make install PREFIX=/usr/andy/redis-cluster
在redis-cluster下 修改bin文件夾為redis01,復(fù)制redis.conf配置文件
創(chuàng)建目錄redis-cluster并在此目錄下再創(chuàng)建7000 7001 7002 7003 7004 7005共6個目錄,在7000中創(chuàng)建配置文件redis.conf婉烟,內(nèi)容如下:
daemonize yes #后臺啟動
port 7001 #修改端口號娩井,從7001到7006
cluster-enabled yes #開啟cluster,去掉注釋
cluster-config-file nodes.conf #自動生成
cluster-node-timeout 15000 #節(jié)點(diǎn)通信時間
appendonly yes #持久化方式
同時把redis.conf復(fù)制到其它目錄中
2似袁、安裝redis-trib所需的 ruby腳本
注意:centos7默認(rèn)的ruby版本太低(2.0)洞辣,要卸載重裝(最低2.2)
yum remove ruby
yum install ruby
yum install rubygems
復(fù)制redis解壓文件src下的redis-trib.rb文件到redis-cluster目錄并安裝gem
gem install redis-3.x.x.gem
若不想安裝src目錄下的gem,也可以直接gem install redis
昙衅。
注意扬霜,gem install可能會報錯
Unable to require openssl,install OpenSSL and rebuild ruby (preferred) or use ....
解決步驟:
- yum install openssl-devel -y
- 在ruby安裝包/root/ruby-x.x.x/ext/openssl,執(zhí)行ruby ./extconf.rb
- 執(zhí)行make,若出現(xiàn)make: *** No rule to make target
/include/ruby.h', needed by
ossl.o'. Stop.;在Makefile頂部中的增加top_srcdir = ../..
- 執(zhí)行make install
3而涉、啟動所有的redis節(jié)點(diǎn)
可以寫一個命令腳本start-all.sh
cd 7000
redis-server redis.conf
cd ..
cd 7001
redis-server redis.conf
cd ..
cd 7002
redis-server redis.conf
cd ..
cd 7003
redis-server redis.conf
cd ..
cd 7004
redis-server redis.conf
cd ..
cd 7005
redis-server redis.conf
cd ..
設(shè)置權(quán)限啟動
[root@localhost redis-cluster]# chmod 777 start-all.sh
[root@localhost redis-cluster]# ./start-all.sh
查看redis進(jìn)程啟動狀態(tài)
[root@localhost redis-4.0.2]# ps -ef|grep cluster
root 54956 1 0 19:17 ? 00:00:00 redis-server *:7000 [cluster]
root 54961 1 0 19:17 ? 00:00:00 redis-server *:7001 [cluster]
root 54966 1 0 19:17 ? 00:00:00 redis-server *:7002 [cluster]
root 54971 1 0 19:17 ? 00:00:00 redis-server *:7003 [cluster]
root 54976 1 0 19:17 ? 00:00:00 redis-server *:7004 [cluster]
root 54981 1 0 19:17 ? 00:00:00 redis-server *:7005 [cluster]
root 55071 24089 0 19:24 pts/0 00:00:00 grep --color=auto cluster
可以看到redis的6個節(jié)點(diǎn)已經(jīng)啟動成功
注意:這里并沒有創(chuàng)建集群
4著瓶、使用redis-trib.rb創(chuàng)建集群
注意:redis-trib.rb在redis/src目錄下。
./redis-trib.rb create --replicas 1 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 127.0.0.1:7000
使用create命令 --replicas 1 參數(shù)表示為每個主節(jié)點(diǎn)創(chuàng)建一個從節(jié)點(diǎn)啼县,其他參數(shù)是實(shí)例的地址集合蟹但。
[root@localhost redis]# ./src/redis-trib.rb create --replicas 1 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 127.0.0.1:7000
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:7001
127.0.0.1:7002
127.0.0.1:7003
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
Adding replica 127.0.0.1:7000 to 127.0.0.1:7003
M: f4ee0a501f9aaf11351787a46ffb4659d45b7bd7 127.0.0.1:7001
slots:0-5460 (5461 slots) master
M: 671a0524a616da8b2f50f3d11a74aaf563578e41 127.0.0.1:7002
slots:5461-10922 (5462 slots) master
M: 18948dab5b07e3726afd1b6a42d5bf6e2f411ba1 127.0.0.1:7003
slots:10923-16383 (5461 slots) master
S: 34e322ca50a2842e9f3664442cb11c897defba06 127.0.0.1:7004
replicates f4ee0a501f9aaf11351787a46ffb4659d45b7bd7
S: 62a00566233fbff4467c4031345b1db13cf12b46 127.0.0.1:7005
replicates 671a0524a616da8b2f50f3d11a74aaf563578e41
S: 2cb649ad3584370c960e2036fb01db834a546114 127.0.0.1:7000
replicates 18948dab5b07e3726afd1b6a42d5bf6e2f411ba1
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:7001)
M: f4ee0a501f9aaf11351787a46ffb4659d45b7bd7 127.0.0.1:7001
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: 671a0524a616da8b2f50f3d11a74aaf563578e41 127.0.0.1:7002
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 2cb649ad3584370c960e2036fb01db834a546114 127.0.0.1:7000
slots: (0 slots) slave
replicates 18948dab5b07e3726afd1b6a42d5bf6e2f411ba1
S: 34e322ca50a2842e9f3664442cb11c897defba06 127.0.0.1:7004
slots: (0 slots) slave
replicates f4ee0a501f9aaf11351787a46ffb4659d45b7bd7
M: 18948dab5b07e3726afd1b6a42d5bf6e2f411ba1 127.0.0.1:7003
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 62a00566233fbff4467c4031345b1db13cf12b46 127.0.0.1:7005
slots: (0 slots) slave
replicates 671a0524a616da8b2f50f3d11a74aaf563578e41
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
上面顯示創(chuàng)建成功,有3個主節(jié)點(diǎn)谭羔,3個從節(jié)點(diǎn)华糖,每個節(jié)點(diǎn)都是成功連接狀態(tài)。
三瘟裸、redis集群的測試
測試存取值客叉,客戶端連接集群redis-cli需要帶上 -c ,redis-cli -c -p 端口號
[root@localhost redis]# ./redis-cli -c -p 7001
127.0.0.1:7001> set name andy
-> Redirected to slot [5798] located at 127.0.0.1:7002
OK
127.0.0.1:7002> get name
"andy"
127.0.0.1:7002>
根據(jù)redis-cluster的key值分配话告,name應(yīng)該分配到節(jié)點(diǎn)7002[5461-10922]上兼搏,上面顯示redis cluster自動從7001跳轉(zhuǎn)到了7002節(jié)點(diǎn)。
測試一下7000從節(jié)點(diǎn)獲取name值
[root@localhost redis]# ./redis-cli -c -p 7000
127.0.0.1:7000> get name
-> Redirected to slot [5798] located at 127.0.0.1:7002
"andy"
127.0.0.1:7002>
四沙郭、集群節(jié)點(diǎn)選舉
現(xiàn)在模擬將7002節(jié)點(diǎn)掛掉佛呻,按照redis-cluster原理會選舉會將 7002的從節(jié)點(diǎn)7005選舉為主節(jié)點(diǎn)。
[root@localhost redis-cluster]# ps -ef | grep redis
root 7966 1 0 12:50 ? 00:00:29 ./redis-server 127.0.0.1:7000 [cluster]
root 7950 1 0 12:50 ? 00:00:28 ./redis-server 127.0.0.1:7001 [cluster]
root 7952 1 0 12:50 ? 00:00:29 ./redis-server 127.0.0.1:7002 [cluster]
root 7956 1 0 12:50 ? 00:00:29 ./redis-server 127.0.0.1:7003 [cluster]
root 7960 1 0 12:50 ? 00:00:29 ./redis-server 127.0.0.1:7004 [cluster]
root 7964 1 0 12:50 ? 00:00:29 ./redis-server 127.0.0.1:7005 [cluster]
root 11346 10581 0 14:57 pts/2 00:00:00 grep --color=auto redis
[root@localhost redis-cluster]# kill 7952
在查看集群中的7002節(jié)點(diǎn)
[root@localhost src]# ./redis-trib.rb check 127.0.0.1:7002
>>> Performing Cluster Check (using node 127.0.0.1:7002)
S: 671a0524a616da8b2f50f3d11a74aaf563578e41 127.0.0.1:7002
slots: (0 slots) slave
replicates 62a00566233fbff4467c4031345b1db13cf12b46
M: 18948dab5b07e3726afd1b6a42d5bf6e2f411ba1 127.0.0.1:7003
slots:10923-16383 (5461 slots) master
1 additional replica(s)
M: 62a00566233fbff4467c4031345b1db13cf12b46 127.0.0.1:7005
slots:5461-10922 (5462 slots) master
1 additional replica(s)
M: f4ee0a501f9aaf11351787a46ffb4659d45b7bd7 127.0.0.1:7001
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 34e322ca50a2842e9f3664442cb11c897defba06 127.0.0.1:7004
slots: (0 slots) slave
replicates f4ee0a501f9aaf11351787a46ffb4659d45b7bd7
S: 2cb649ad3584370c960e2036fb01db834a546114 127.0.0.1:7000
slots: (0 slots) slave
replicates 18948dab5b07e3726afd1b6a42d5bf6e2f411ba1
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
可以看到集群連接不了7002節(jié)點(diǎn)病线,而7005有原來的S轉(zhuǎn)換為M節(jié)點(diǎn)吓著,代替了原來的7002節(jié)點(diǎn)。我們可以獲取name值:
[root@localhost redis]# ./redis-cli -c -p 7001
127.0.0.1:7001> get name
-> Redirected to slot [5798] located at 127.0.0.1:7005
"andy"
127.0.0.1:7005>
127.0.0.1:7005>
從7001節(jié)點(diǎn)連入送挑,自動跳轉(zhuǎn)到7005節(jié)點(diǎn)绑莺,并且獲取name值。
現(xiàn)在我們將7002節(jié)點(diǎn)恢復(fù)惕耕,看是否會自動加入集群中以及充當(dāng)?shù)腗還是S節(jié)點(diǎn)纺裁。
[root@localhost redis-cluster]# cd 7002
[root@localhost 7002]# ./redis-server redis.conf
[root@localhost 7002]#
再check一下7002節(jié)點(diǎn),可以看到7002節(jié)點(diǎn)變成了7005的從節(jié)點(diǎn)。
學(xué)習(xí)交流群:64691032