模式二:Cluster集群
由于redis集群的理論還有實(shí)踐都比較復(fù)雜膊畴,所以我們將把實(shí)操和理論分為兩篇文章介紹,這篇文章首先介紹實(shí)操環(huán)節(jié)棠绘。
Redis3.0之后的止,節(jié)點(diǎn)之間通過去中心化的方式提供了完整的sharding(分片),replication(復(fù)制),failover(故障遷移)解決方案,成為redis-cluster
Redis 集群是一個(gè)可以在多個(gè) Redis 節(jié)點(diǎn)之間進(jìn)行數(shù)據(jù)共享的設(shè)施
并且集群特性不支持跨節(jié)點(diǎn)的keys命令骗污,并且通過分區(qū)來保證當(dāng)一個(gè)節(jié)點(diǎn)失效時(shí)其他節(jié)點(diǎn)可以繼續(xù)工作崇猫。
redis集群的優(yōu)勢(shì):
- 自動(dòng)分割數(shù)據(jù)到不同的節(jié)點(diǎn)上。
- 整個(gè)集群的部分節(jié)點(diǎn)失敗或者不可達(dá)的情況下能夠繼續(xù)處理命令
redis集群并沒有使用一致性hash,而是引入了哈希槽(slot)的概念需忿,redis集群共有16384個(gè)slot,每一個(gè)key通過一定的計(jì)算方式分配到不同的slot上诅炉,然后每一個(gè)節(jié)點(diǎn)負(fù)責(zé)一部分的slot.
舉例,比如當(dāng)前集群有三個(gè)節(jié)點(diǎn)屋厘,那么:
- 節(jié)點(diǎn) A 包含 0 到 5500號(hào)哈希槽.
- 節(jié)點(diǎn) B 包含5501 到 11000 號(hào)哈希槽.
- 節(jié)點(diǎn) C 包含11001 到 16384號(hào)哈希槽.
這種結(jié)構(gòu)的優(yōu)點(diǎn)就是很容易的添加或刪除節(jié)點(diǎn)涕烧,比如我想新添加一個(gè)節(jié)點(diǎn)D,我們需要從A,B,C中的部分槽轉(zhuǎn)移到D擅这,如果我想移除節(jié)點(diǎn)A,需要將A中的槽移到B和C節(jié)點(diǎn)上,然后將沒有任何槽的A節(jié)點(diǎn)從集群中移除即可.由于從一個(gè)節(jié)點(diǎn)將哈希槽移動(dòng)到另一個(gè)節(jié)點(diǎn)并不會(huì)停止服務(wù),所以無論添加刪除或者改變某個(gè)節(jié)點(diǎn)的哈希槽的數(shù)量都不會(huì)造成集群不可用的狀態(tài).
搭建并使用redis集群:
這里我們準(zhǔn)備搭建三個(gè)節(jié)點(diǎn)的集群澈魄,每個(gè)節(jié)點(diǎn)一主一備。將redis下載下來解壓后復(fù)制六份仲翎,端口號(hào)分別置為6380痹扇,6381,6382溯香,6383鲫构,6384,6385.
修改redis.windows.conf配置
port 6380
cluster-enabled yes //開啟集群模式
cluster-config-file nodes-6380.conf //保存節(jié)點(diǎn)配置文件的路徑
cluster-node-timeout 15000 //節(jié)點(diǎn)超時(shí)時(shí)間
每個(gè)實(shí)例都按照對(duì)應(yīng)的端口號(hào)進(jìn)行修改玫坛,然后將六個(gè)實(shí)例都運(yùn)行起來
集群啟動(dòng)需要用到命令行工具redis-trib结笨,而這個(gè)工具是一個(gè)ruby程序,因此我們需要安裝ruby,
下載地址:http://dl.bintray.com/oneclick/rubyinstaller/rubyinstaller-2.2.4-x64.exe
下載下來后按照步驟安裝湿镀,最后一步勾選全部如圖:
下載ruby環(huán)境redis驅(qū)動(dòng)
下載地址:https://rubygems.org/gems/redis/versions/3.2.2
如圖:
將下載下來的文件放入ruby安裝目錄下炕吸,如圖:
安裝該驅(qū)動(dòng),命令如下:
gem install --local C:\Ruby22-x64\redis-3.2.2.gem
如圖表示成功:
環(huán)境準(zhǔn)備完畢勉痴,我們需要在redis的github上找到redis-trib.rb文件(集群命令工具
)
鏈接:https://github.com/microsoftarchive/redis/tree/3.0/src
在src文件夾下有如下文件:
copy下來后放在redis文件夾下如圖:
此時(shí)一切準(zhǔn)備就緒赫模,腳本創(chuàng)建集群
redis-trib.rb create --replicas 1 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 127.0.0.1:6385
選項(xiàng)–replicas 1 表示我們希望為集群中的每個(gè)主節(jié)點(diǎn)創(chuàng)建一個(gè)從節(jié)點(diǎn)
執(zhí)行后出現(xiàn)如圖
在輸入yes后,運(yùn)行如下表示成功:
上圖表示集群中的 16384 個(gè)槽都有至少一個(gè)主節(jié)點(diǎn)在處理蒸矛, 集群運(yùn)作正常瀑罗。
此時(shí)我們查看集群情況,如圖:
從上圖我們可以看出雏掠,redis目前模式是cluster模式斩祭,自動(dòng)分配6383為從節(jié)點(diǎn)。
我們簡單測試下set功能乡话,如圖
上圖我們可以看出我們?cè)?380set數(shù)據(jù)在從節(jié)點(diǎn)6383以及另外的6382節(jié)點(diǎn)都可以查看到
TODO:在啟動(dòng)集群的時(shí)候可能會(huì)遇到如下報(bào)錯(cuò)摧玫,此時(shí)我們需要在各個(gè)節(jié)點(diǎn)上執(zhí)行下以下命令:然后再重新啟動(dòng)就好了
集群重新分片
現(xiàn)在, 讓我們來試試對(duì)集群進(jìn)行重新分片操作
redis-trib.rb reshard 127.0.0.1:6380命令進(jìn)行重新分片绑青。如下幾張圖
下圖看出開始遷移:
從其他兩個(gè)主節(jié)點(diǎn)開始分slot給6380席赂,如圖:
重新分片完成后我們查看集群情況吮铭,如圖
可以清楚看到slot分配和之前有所不同
測試故障轉(zhuǎn)移
我們首先查看集群的節(jié)點(diǎn)情況,如圖:
可以看出6380颅停,6381谓晌,6382為主節(jié)點(diǎn),我們測試6380宕機(jī)癞揉,自動(dòng)進(jìn)行故障遷移纸肉。
在6380節(jié)點(diǎn)執(zhí)行debug segfault命令,讓主節(jié)點(diǎn)崩潰喊熟,如圖
此時(shí)我們可以看到6383自動(dòng)成為了主節(jié)點(diǎn)柏肪,如圖對(duì)比可以看出效果:
我們?cè)賹?380重啟,已啟動(dòng)我們就可以看到6380成為了6383的從節(jié)點(diǎn)芥牌,同時(shí)在同步主節(jié)點(diǎn)的數(shù)據(jù)烦味,如圖:
手動(dòng)故障遷移
有的時(shí)候在主節(jié)點(diǎn)沒有任何問題的情況下強(qiáng)制手動(dòng)故障轉(zhuǎn)移也是很有必要的,比如想要升級(jí)主節(jié)點(diǎn)的Redis進(jìn)程壁拉,我們可以通過故障轉(zhuǎn)移將其轉(zhuǎn)為slave再進(jìn)行升級(jí)操作來避免對(duì)集群的可用性造成很大的影響谬俄。
Redis集群使用 CLUSTER FAILOVER命令來進(jìn)行故障轉(zhuǎn)移,不過要被轉(zhuǎn)移的主節(jié)點(diǎn)的從節(jié)點(diǎn)上執(zhí)行該命令 手動(dòng)故障轉(zhuǎn)移比主節(jié)點(diǎn)失敗自動(dòng)故障轉(zhuǎn)移更加安全弃理,因?yàn)槭謩?dòng)故障轉(zhuǎn)移時(shí)客戶端的切換是在確保新的主節(jié)點(diǎn)完全復(fù)制了失敗的舊的主節(jié)點(diǎn)數(shù)據(jù)的前提下下發(fā)生的溃论,所以避免了數(shù)據(jù)的丟失。
我們這里由于我們剛剛執(zhí)行了自動(dòng)故障遷移痘昌,6383目前為主钥勋,6380為從,我們這次執(zhí)行手動(dòng)故障遷移辆苔,同樣是這個(gè)節(jié)點(diǎn)算灸,我們?cè)?380從節(jié)點(diǎn)直接上面命令,如圖:
添加一個(gè)新節(jié)點(diǎn)
添加新的節(jié)點(diǎn)的基本過程就是添加一個(gè)空的節(jié)點(diǎn)然后移動(dòng)一些數(shù)據(jù)給它驻啤,有兩種情況乎婿,添加一個(gè)主節(jié)點(diǎn)和添加一個(gè)從節(jié)點(diǎn)
先從添加主節(jié)點(diǎn)開始.
第一步都是要添加 一個(gè)空的節(jié)點(diǎn).同樣還是copy一份redis配置,修改下端口號(hào)即可街佑,這里我們新增一個(gè)6386節(jié)點(diǎn)。
6386節(jié)點(diǎn)啟動(dòng)成功后捍靠,我們執(zhí)行以下命令將節(jié)點(diǎn)加入集群沐旨,如圖:
redis-trib.rb add-node 127.0.0.1:6386 127.0.0.1:6380
此時(shí)我們可以看到6386節(jié)點(diǎn)成功加入集群
然后我們此時(shí)可以向上面所說的重新分片,向6386節(jié)點(diǎn)分配一點(diǎn)slot就可以了榨婆。
添加一個(gè)從節(jié)點(diǎn)
我們接下來添加一個(gè)從節(jié)點(diǎn)進(jìn)入集群磁携,同上述一樣,復(fù)制一份redis文件修改端口號(hào)良风,節(jié)點(diǎn)端口號(hào)為6387谊迄,添加從節(jié)點(diǎn)需要執(zhí)行以下命令:
redis-trib.rb add-node --slave 127.0.0.1:6387 127.0.0.1:6380
結(jié)果如下兩圖:
這種方式并沒有從節(jié)點(diǎn)綁在哪個(gè)主節(jié)點(diǎn)下面闷供,集群會(huì)隨機(jī)分配,我們也可以進(jìn)行指定统诺,新建6388節(jié)點(diǎn)歪脏,啟動(dòng),指令如下:
redis-trib.rb add-node --slave --master-id 87532601dbdcced4cdc6668fdd224d91a7065844 127.0.0.1:6388 127.0.0.1:6380
我們這里指定綁在6381下面粮呢,執(zhí)行之前我們可以看到只有6384是6381的從節(jié)點(diǎn)(這里官網(wǎng)上有查專門從節(jié)點(diǎn)的命令婿失,不知為何一直失敗。啄寡。豪硅。),執(zhí)行完畢后我們可以看到6381從節(jié)點(diǎn)改變?yōu)閮蓚€(gè)挺物。
移除一個(gè)節(jié)點(diǎn)
只要使用 del-node 命令即可:
這里我們移除剛剛新增的6388懒浮,del-node后面為隨意指定一個(gè)集群節(jié)點(diǎn),之后為要?jiǎng)h除的節(jié)點(diǎn)id
redis-trib del-node 127.0.0.1:6380 a6205f7eb6b3e3afa1211b7f80ac11357235e9a6
執(zhí)行之后可以看到6388節(jié)點(diǎn)已經(jīng)不在集群
這里是移除從節(jié)點(diǎn)识藤,我們?cè)囈幌乱瞥鞴?jié)點(diǎn)砚著,這里需要注意移除主節(jié)點(diǎn)之前需要確保主節(jié)點(diǎn)下沒有數(shù)據(jù),比如我們先移除6381蹋岩,如圖:
可以看出由于6381是存在slot的赖草,所以執(zhí)行失敗,我們?cè)僭囍瞥?386剪个,6386是我們上面加入的一個(gè)新的主節(jié)點(diǎn)秧骑,我們?cè)诩尤牒蟛]有分片給它,所以它是不存在數(shù)據(jù)的扣囊,如圖
上圖我們可以看出很順利的就刪除了6386主節(jié)點(diǎn)乎折。
從節(jié)點(diǎn)的遷移
在Redis集群中會(huì)存在改變一個(gè)從節(jié)點(diǎn)的主節(jié)點(diǎn)的情況,需要執(zhí)行如下命令 :
CLUSTER REPLICATE <master-node-id>
目前我們集群6380存在兩個(gè)從節(jié)點(diǎn)6383和6387
我們將6387遷移到6382上侵歇,如圖:
在集群中同樣存在為了保證基金的高可用性骂澄,會(huì)存在自動(dòng)從節(jié)點(diǎn)遷移,以保證主節(jié)點(diǎn)盡量有一個(gè)從節(jié)點(diǎn)惕虑。
這篇文章我們主要介紹了redis集群的搭建過程坟冲,但是具體的集群原理,如怎么分片溃蔫,怎么檢測故障遷移之類的還沒有介紹健提,我們將在下一篇文章介紹。