redis作為一種高效的緩存框架贴届,使用是非常廣泛的慕购,在數(shù)據(jù)存儲(chǔ)上躬络,在運(yùn)行時(shí)其將數(shù)據(jù)存儲(chǔ)在內(nèi)存中尖奔,以實(shí)現(xiàn)數(shù)據(jù)的高效讀寫(xiě),并且根據(jù)定制的持久化規(guī)則不同穷当,其會(huì)不定期的將數(shù)據(jù)持久化到硬盤(pán)中提茁。
另外相較于其他的NoSql數(shù)據(jù)庫(kù),redis提供了非常豐富的數(shù)據(jù)結(jié)構(gòu)馁菜,如dict茴扁,sds,linkedlist火邓,ziplist丹弱,set德撬,quicklist,geometry躲胳。在這些存儲(chǔ)結(jié)構(gòu)的基礎(chǔ)上蜓洪,redis為用戶(hù)提供了非常豐富的操作選擇,如通過(guò)zskiplist來(lái)達(dá)到對(duì)某種類(lèi)型的數(shù)據(jù)的排序目的坯苹,而排序在數(shù)據(jù)庫(kù)中是一個(gè)非常耗時(shí)的操作隆檀。
1.redis單例的安裝和使用
redis相對(duì)于其他的緩存框架安裝非常的方便,只需要從https://redis.io/download下載后解壓粹湃,進(jìn)入redis目錄之后執(zhí)行如下命令即安裝完成:
make install
這里需要注意的是make是gcc中的一個(gè)命令恐仑,安裝之前請(qǐng)確保機(jī)器安裝了gcc。redis中所有的命令都在redis安裝目錄中的src子目錄下为鳄,其中比較重要的是redis-server裳仆,redis-sentinel,redis-cli孤钦。
編譯完成之后在src目錄下執(zhí)行./redis-server啟動(dòng)redis(啟動(dòng)后可關(guān)閉該窗口)歧斟,然后新開(kāi)一個(gè)窗口,在命令行中執(zhí)行./redis-cli即可連接啟動(dòng)的redis服務(wù)偏形。在其中執(zhí)行如下命令即可看到編譯安裝成功了:
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> get hello
"world"
這里需要說(shuō)明的是静袖,按照上述方式啟動(dòng)redis,其使用的ip為本機(jī)ip 127.0.0.1俊扭,端口為6379队橙,并且其余的配置采用的都是默認(rèn)配置,相關(guān)配置可在redis安裝目錄下的redis.conf文件中查看萨惑。如果需要按照指定的配置文件來(lái)啟動(dòng)捐康,可在redis-server后接上配置文件名,如:
./src/redis-server redis.conf
另外咒钟,上述使用redis-cli連接redis客戶(hù)端時(shí)如果不帶任何參數(shù)吹由,那么其連接的默認(rèn)ip和端口為127.0.0.1:6379。如果需要連接指定ip和端口的客戶(hù)端朱嘴,可以使用如下方式:
./src/redis-cli -h 127.0.0.1 -p 6379
這里-h參數(shù)表示連接的ip,-p則表示連接的端口粗合。配置好redis之后萍嬉,我們就可以在redis中執(zhí)行相關(guān)命令來(lái)操作數(shù)據(jù)。
2.redis主從模式的配置
redis單例提供了一種數(shù)據(jù)緩存方式和豐富的數(shù)據(jù)操作api隙疚,但是將數(shù)據(jù)完全存儲(chǔ)在單個(gè)redis中主要存在兩個(gè)問(wèn)題:數(shù)據(jù)備份和數(shù)據(jù)體量較大造成的性能降低壤追。這里redis的主從模式為這兩個(gè)問(wèn)題提供了一個(gè)較好的解決方案。
主從模式指的是使用一個(gè)redis實(shí)例作為主機(jī)供屉,其余的實(shí)例作為備份機(jī)行冰。主機(jī)和從機(jī)的數(shù)據(jù)完全一致溺蕉,主機(jī)支持?jǐn)?shù)據(jù)的寫(xiě)入和讀取等各項(xiàng)操作,而從機(jī)則只支持與主機(jī)數(shù)據(jù)的同步和讀取悼做,也就是說(shuō)疯特,客戶(hù)端可以將數(shù)據(jù)寫(xiě)入到主機(jī),由主機(jī)自動(dòng)將數(shù)據(jù)的寫(xiě)入操作同步到從機(jī)肛走。
主從模式很好的解決了數(shù)據(jù)備份問(wèn)題漓雅,并且由于主從服務(wù)數(shù)據(jù)幾乎是一致的,因而可以將寫(xiě)入數(shù)據(jù)的命令發(fā)送給主機(jī)執(zhí)行朽色,而讀取數(shù)據(jù)的命令發(fā)送給不同的從機(jī)執(zhí)行邻吞,從而達(dá)到讀寫(xiě)分離的目的。如下所示主機(jī)redis-A分別有redis-B葫男、redis-C抱冷、redis-D、redis-E四個(gè)從機(jī):
前面第1點(diǎn)中我們已經(jīng)介紹了redis單例的配置方式梢褐,而上面我們也介紹了主從模式其實(shí)也是多個(gè)redis實(shí)例組成的旺遮,因而redis主從模式的配置可以理解為多個(gè)不同的redis實(shí)例通過(guò)一定的配置告知其相互之間的主從關(guān)系。
而前面已經(jīng)介紹利职,每個(gè)redis實(shí)例都會(huì)占用一個(gè)本機(jī)的端口號(hào)趣效,主從模式的配置主要的配置點(diǎn)有兩個(gè):當(dāng)前實(shí)例端口號(hào)和當(dāng)前實(shí)例是主機(jī)還是從機(jī),是從機(jī)的話(huà)其主機(jī)的ip和端口是什么猪贪。一般的redis目錄下的redis.conf保存的是默認(rèn)配置跷敬,盡量不要對(duì)其進(jìn)行修改,這里我們復(fù)制三份redis.conf文件热押,分別命名為6379.conf西傀,6380.conf和6381.conf,如下是端口為6379的主機(jī)的主要配置:
bind 127.0.0.1
port 6379
logfile "6379.log"
dbfilename "dump-6379.rdb"
如下是端口為6380和6381的從機(jī)的配置:
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的實(shí)例被配置為端口為6379的實(shí)例的從機(jī)拥褂。配置完成后使用redis-server分別執(zhí)行如下命令啟動(dòng)三個(gè)實(shí)例:
./src/redis-server 6379.conf
./src/redis-server 6380.conf
./src/redis-server 6381.conf
啟動(dòng)之后分別開(kāi)啟開(kāi)啟三個(gè)命令行工具分別執(zhí)行以下命令連接redis實(shí)例:
./src/redis-cli -p 6379
./src/redis-cli -p 6380
./src/redis-cli -p 6381
分別在三個(gè)命令行工具中執(zhí)行一個(gè)get命令,獲取鍵名為msg的數(shù)據(jù)牙寞,如下所示:
127.0.0.1:6379> get msg
(nil)
127.0.0.1:6380> get msg
(nil)
127.0.0.1:6381> get msg
(nil)
可以看到饺鹃,在三個(gè)redis實(shí)例中都不存在鍵為msg的數(shù)據(jù),現(xiàn)在我們?cè)谥鳈C(jī)6379上設(shè)置一個(gè)鍵為msg的數(shù)據(jù)间雀,如下所示:
127.0.0.1:6379> set msg "hello"
OK
可以看到設(shè)置成功了悔详,此時(shí)我們?cè)?380和6381的實(shí)例上執(zhí)行g(shù)et msg的命令,如下所示:
127.0.0.1:6380> get msg
"hello"
127.0.0.1:6381> get msg
"hello"
可以看到惹挟,雖然我們只是在6379的實(shí)例上設(shè)置了msg這條數(shù)據(jù)茄螃,但是在6380和6381的實(shí)例上也存有了相應(yīng)的數(shù)據(jù),說(shuō)明我們成功配置了redis的主從模式连锯。另外归苍,如果不在配置文件中指定主從節(jié)點(diǎn)的關(guān)系用狱,也可以在啟動(dòng)相關(guān)redis實(shí)例之后使用slaveof命令來(lái)指定當(dāng)前節(jié)點(diǎn)稱(chēng)為某個(gè)節(jié)點(diǎn)的從節(jié)點(diǎn),如:
127.0.0.1:6380> slaveof 127.0.0.1 6379
3.redis中sentinel配置
redis主從模式解決了數(shù)據(jù)備份和單例可能存在的性能問(wèn)題拼弃,但是其也引入了新的問(wèn)題夏伊。由于主從模式配置了三個(gè)redis實(shí)例,并且每個(gè)實(shí)例都使用不同的ip(如果在不同的機(jī)器上)和端口號(hào)肴敛,根據(jù)前面所述署海,主從模式下可以將讀寫(xiě)操作分配給不同的實(shí)例進(jìn)行從而達(dá)到提高系統(tǒng)吞吐量的目的,但也正是因?yàn)檫@種方式造成了使用上的不便医男,因?yàn)槊總€(gè)客戶(hù)端連接redis實(shí)例的時(shí)候都是指定了ip和端口號(hào)的砸狞,如果所連接的redis實(shí)例因?yàn)楣收舷戮€(xiàn)了,而主從模式也沒(méi)有提供一定的手段通知客戶(hù)端另外可連接的客戶(hù)端地址镀梭,因而需要手動(dòng)更改客戶(hù)端配置重新連接刀森。另外,主從模式下报账,如果主節(jié)點(diǎn)由于故障下線(xiàn)了研底,那么從節(jié)點(diǎn)因?yàn)闆](méi)有主節(jié)點(diǎn)而同步中斷,因而需要人工進(jìn)行故障轉(zhuǎn)移工作透罢。
為了解決這兩個(gè)問(wèn)題榜晦,在2.8版本之后redis正式提供了sentinel(哨兵)架構(gòu)。關(guān)于sentinel羽圃,這里需要說(shuō)明幾個(gè)概念:
每個(gè)sentinel節(jié)點(diǎn)其實(shí)就是一個(gè)redis實(shí)例乾胶,與主從節(jié)點(diǎn)不同的是sentinel節(jié)點(diǎn)作用是用于監(jiān)控redis數(shù)據(jù)節(jié)點(diǎn)的,而sentinel節(jié)點(diǎn)集合則表示監(jiān)控一組主從redis實(shí)例多個(gè)sentinel監(jiān)控節(jié)點(diǎn)的集合朽寞,比如有主節(jié)點(diǎn)master和從節(jié)點(diǎn)slave-1识窿、slave-2,為了監(jiān)控這三個(gè)主從節(jié)點(diǎn)脑融,這里配置N個(gè)sentinel節(jié)點(diǎn)sentinel-1喻频,sentinel-2,...肘迎,sentinel-N甥温。如下圖是sentinel監(jiān)控主從節(jié)點(diǎn)的示例圖:
從圖中可以看出,對(duì)于一組主從節(jié)點(diǎn)妓布,sentinel只是在其外部額外添加的一組用于監(jiān)控作用的redis實(shí)例窿侈。在主從節(jié)點(diǎn)和sentinel節(jié)點(diǎn)集合配置好之后,sentinel節(jié)點(diǎn)之間會(huì)相互發(fā)送消息秋茫,以檢測(cè)其余sentinel節(jié)點(diǎn)是否正常工作,并且sentinel節(jié)點(diǎn)也會(huì)向主從節(jié)點(diǎn)發(fā)送消息乃秀,以檢測(cè)監(jiān)控的主從節(jié)點(diǎn)是否正常工作肛著。
前面講到圆兵,sentinel架構(gòu)的主要作用是解決主從模式下主節(jié)點(diǎn)的故障轉(zhuǎn)移工作的。這里如果主節(jié)點(diǎn)因?yàn)楣收舷戮€(xiàn)枢贿,那么某個(gè)sentinel節(jié)點(diǎn)發(fā)送檢測(cè)消息給主節(jié)點(diǎn)時(shí)殉农,如果在指定時(shí)間內(nèi)收不到回復(fù),那么該sentinel就會(huì)主觀(guān)的判斷該主節(jié)點(diǎn)已經(jīng)下線(xiàn)局荚,那么其會(huì)發(fā)送消息給其余的sentinel節(jié)點(diǎn)超凳,詢(xún)問(wèn)其是否“認(rèn)為”該主節(jié)點(diǎn)已下線(xiàn),其余的sentinel收到消息后也會(huì)發(fā)送檢測(cè)消息給主節(jié)點(diǎn)耀态。
如果其認(rèn)為該主節(jié)點(diǎn)已經(jīng)下線(xiàn)轮傍,那么其會(huì)回復(fù)向其詢(xún)問(wèn)的sentinel節(jié)點(diǎn),告知其也認(rèn)為主節(jié)點(diǎn)已經(jīng)下線(xiàn)首装,當(dāng)該sentinel節(jié)點(diǎn)最先收到超過(guò)指定數(shù)目(配置文件中配置的數(shù)目和當(dāng)前sentinel節(jié)點(diǎn)集合數(shù)的一半创夜,這里兩個(gè)數(shù)目的較大值)的sentinel節(jié)點(diǎn)回復(fù)說(shuō)當(dāng)前主節(jié)點(diǎn)已下線(xiàn),那么其就會(huì)對(duì)主節(jié)點(diǎn)進(jìn)行故障轉(zhuǎn)移工作仙逻,故障轉(zhuǎn)移的基本思路是在從節(jié)點(diǎn)中選取某個(gè)從節(jié)點(diǎn)向其發(fā)送slaveof no one(假設(shè)選取的從節(jié)點(diǎn)為127.0.0.1:6380)驰吓,使其稱(chēng)為獨(dú)立的節(jié)點(diǎn)(也就是新的主節(jié)點(diǎn)),然后sentinel向其余的從節(jié)點(diǎn)發(fā)送slaveof 127.0.0.1 6380命令使它們重新成為新的主節(jié)點(diǎn)的從節(jié)點(diǎn)系奉。
重新分配之后sentinel節(jié)點(diǎn)集合還會(huì)繼續(xù)監(jiān)控已經(jīng)下線(xiàn)的主節(jié)點(diǎn)(假設(shè)為127.0.0.1:6379)檬贰,如果其重新上線(xiàn),那么sentinel會(huì)向其發(fā)送slaveof命令缺亮,使其成為新的主機(jī)點(diǎn)的從節(jié)點(diǎn)翁涤,如此故障轉(zhuǎn)移工作完成。
上面我們講到了瞬内,每個(gè)sentinel節(jié)點(diǎn)在本質(zhì)上還是一個(gè)redis實(shí)例迷雪,只不過(guò)和redis數(shù)據(jù)節(jié)點(diǎn)不同的是,其主要作用是監(jiān)控redis數(shù)據(jù)節(jié)點(diǎn)虫蝶。在redis安裝目錄下有個(gè)默認(rèn)的sentinel配置文件sentinel.conf章咧,和配置主從節(jié)點(diǎn)類(lèi)似,這里復(fù)制三個(gè)配置文件:sentinel-26379.conf能真,sentinel-26380.conf和sentinel-26381.conf赁严。分別按照如下示例編輯這三個(gè)配置文件:
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
對(duì)于端口為26380和26381的sentinel,其配置和上述類(lèi)似粉铐,只需要把相應(yīng)的端口號(hào)修改為對(duì)應(yīng)的端口號(hào)即可疼约。這里注意兩點(diǎn):
每個(gè)sentinel的myid參數(shù)也要進(jìn)行修改,因?yàn)閟entinel之間是通過(guò)該屬性來(lái)唯一區(qū)分其他sentinel節(jié)點(diǎn)的蝙泼;
參數(shù)中sentinel monitor mymaster 127.0.0.1 6379 2這里的端口號(hào)6379是不用更改的程剥,因?yàn)閟entinel是通過(guò)檢測(cè)主節(jié)點(diǎn)的狀態(tài)來(lái)得知當(dāng)前主節(jié)點(diǎn)的從節(jié)點(diǎn)有哪些的,因而設(shè)置為主節(jié)點(diǎn)的端口號(hào)即可汤踏。
配置完成后我們首先啟動(dòng)三個(gè)主從節(jié)點(diǎn)织鲸,然后分別使用三個(gè)配置文件使用如下命令啟用sentinel:
./src/redis-sentinel sentinel-26379.conf
./src/redis-sentinel sentinel-26380.conf
./src/redis-sentinel sentinel-26381.conf
由于sentinel節(jié)點(diǎn)也是一個(gè)redis實(shí)例舔腾,因而我們可以通過(guò)如下命令使用redis-cli連接sentinel節(jié)點(diǎn):
./src/redis-cli -p 26379
連上sentinel節(jié)點(diǎn)之后我們可以通過(guò)如下命令查看sentinel狀態(tài):
127.0.0.1:26379> info sentinel
結(jié)果如下:
# 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檢測(cè)到主從節(jié)點(diǎn)總共有三個(gè)搂擦,其中一個(gè)主節(jié)點(diǎn)稳诚,兩個(gè)從節(jié)點(diǎn),并且sentinel節(jié)點(diǎn)總共也有三個(gè)瀑踢。啟動(dòng)完成之后扳还,我們可以通過(guò)主動(dòng)下線(xiàn)主節(jié)點(diǎn)來(lái)模擬sentinel的故障轉(zhuǎn)移過(guò)程。首先我們連接上端口為6379的主節(jié)點(diǎn)橱夭,使用如下命令查看主從節(jié)點(diǎn)狀態(tài):
127.0.0.1:6379> info replication
結(jié)果如下:
# 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
可以看到氨距,當(dāng)前主節(jié)點(diǎn)有兩個(gè)從節(jié)點(diǎn),端口分別為6380和6381徘钥。然后我們對(duì)主節(jié)點(diǎn)執(zhí)行如下命令:
127.0.0.1:6379> shutdown save
然后我們連接上端口號(hào)為6380的從節(jié)點(diǎn)衔蹲,并執(zhí)行如下命令:
127.0.0.1:6380> info replication
結(jié)果如下:
# 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
可以看到,當(dāng)端口為6379的實(shí)例下線(xiàn)之后呈础,端口為6380的實(shí)例被重新競(jìng)選為新的主節(jié)點(diǎn)舆驶,并且端口為6381的實(shí)例被設(shè)置為6380的實(shí)例的從節(jié)點(diǎn)。如果我們此時(shí)重新啟用端口為6379的節(jié)點(diǎn)而钞,然后再查看主從狀態(tài)沙廉,結(jié)果如下:
# 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實(shí)例重新連接后臼节,sentinel節(jié)點(diǎn)檢測(cè)到其重新連接撬陵,那么對(duì)其發(fā)送命令,使其成為新的主節(jié)點(diǎn)的從節(jié)點(diǎn)网缝。
4.redis集群的配置
redis集群是在redis 3.0版本推出的一個(gè)功能巨税,其有效的解決了redis在分布式方面的需求。當(dāng)遇到單機(jī)內(nèi)存粉臊,并發(fā)和流量瓶頸等問(wèn)題時(shí)草添,可采用Cluster方案達(dá)到負(fù)載均衡的目的。并且從另一方面講扼仲,redis中sentinel有效的解決了故障轉(zhuǎn)移的問(wèn)題远寸,也解決了主節(jié)點(diǎn)下線(xiàn)客戶(hù)端無(wú)法識(shí)別新的可用節(jié)點(diǎn)的問(wèn)題,但是如果是從節(jié)點(diǎn)下線(xiàn)了屠凶,sentinel是不會(huì)對(duì)其進(jìn)行故障轉(zhuǎn)移的驰后,并且連接從節(jié)點(diǎn)的客戶(hù)端也無(wú)法獲取到新的可用從節(jié)點(diǎn),而這些問(wèn)題在Cluster中都得到了有效的解決矗愧。
redis集群中數(shù)據(jù)是和槽(slot)掛鉤的灶芝,其總共定義了16384個(gè)槽,所有的數(shù)據(jù)根據(jù)一致哈希算法會(huì)被映射到這16384個(gè)槽中的某個(gè)槽中;另一方面监署,這16384個(gè)槽是按照設(shè)置被分配到不同的redis節(jié)點(diǎn)上的颤专。
比如啟動(dòng)了三個(gè)redis實(shí)例:cluster-A,cluster-B和cluster-C钠乏,這里將0-5460號(hào)槽分配給cluster-A,將5461-10922號(hào)槽分配給cluster-B春塌,將10923-16383號(hào)槽分配給cluster-C(總共有16384個(gè)槽晓避,但是其標(biāo)號(hào)類(lèi)似數(shù)組下標(biāo),是從0到16383)只壳。也就是說(shuō)數(shù)據(jù)的存儲(chǔ)只和槽有關(guān)俏拱,并且槽的數(shù)量是一定的,由于一致hash算法是一定的吼句,因而將這16384個(gè)槽分配給無(wú)論多少個(gè)redis實(shí)例锅必,對(duì)于確認(rèn)的數(shù)據(jù)其都將被分配到確定的槽位上。redis集群通過(guò)這種方式來(lái)達(dá)到redis的高效和高可用性目的惕艳。
這里需要進(jìn)行說(shuō)明的一點(diǎn)是搞隐,一致哈希算法根據(jù)數(shù)據(jù)的key值計(jì)算映射位置時(shí)和所使用的節(jié)點(diǎn)數(shù)量有非常大的關(guān)系。一致哈希分區(qū)的實(shí)現(xiàn)思路是為系統(tǒng)中每個(gè)節(jié)點(diǎn)分配一個(gè)token远搪,范圍一般在0~2^32劣纲,這些token構(gòu)成一個(gè)哈希環(huán),數(shù)據(jù)讀寫(xiě)執(zhí)行節(jié)點(diǎn)查找操作時(shí)谁鳍,先根據(jù)key計(jì)算hash值癞季,然后順時(shí)針找到第一個(gè)大于等于該hash值的token節(jié)點(diǎn),需要操作的數(shù)據(jù)就保存在該節(jié)點(diǎn)上倘潜。通過(guò)分析可以發(fā)現(xiàn)绷柒,一致哈希分區(qū)存在如下問(wèn)題:
加減節(jié)點(diǎn)會(huì)造成哈希環(huán)中部分?jǐn)?shù)據(jù)無(wú)法命中,需要手動(dòng)處理或忽略這部分?jǐn)?shù)據(jù)涮因;
當(dāng)使用少量節(jié)點(diǎn)時(shí)废睦,節(jié)點(diǎn)變化將大范圍影響環(huán)中數(shù)據(jù)映射,因此這種方式不適合少量節(jié)點(diǎn)的分布式方案蕊退;
普通的一致性哈希分區(qū)在增減節(jié)點(diǎn)時(shí)需要增加一倍或減去一半節(jié)點(diǎn)才能保證數(shù)據(jù)和負(fù)載的平衡郊楣。
正是由于一致哈希分區(qū)的這些問(wèn)題,redis使用了虛擬槽來(lái)處理分區(qū)時(shí)節(jié)點(diǎn)變化的問(wèn)題瓤荔,也即將所有的數(shù)據(jù)映射到16384個(gè)虛擬槽位上净蚤,當(dāng)redis節(jié)點(diǎn)變化時(shí)數(shù)據(jù)映射的槽位將不會(huì)變化,并且這也是redis進(jìn)行節(jié)點(diǎn)擴(kuò)張的基礎(chǔ)输硝。
對(duì)于redis集群的配置今瀑,首先將redis安裝目錄下的redis.conf文件復(fù)制六份,分別取名為:cluster-6379.conf、cluster-6380.conf橘荠、cluster-6381.conf屿附、cluster-6382.conf、cluster-6383.conf哥童、cluster-6384.conf挺份。對(duì)于一個(gè)高可用的集群方案,集群每個(gè)節(jié)點(diǎn)都將為其分配一個(gè)從節(jié)點(diǎn)贮懈,以防止數(shù)據(jù)節(jié)點(diǎn)因?yàn)楣收舷戮€(xiàn)匀泊,這里使用六份配置文件定義六個(gè)redis實(shí)例,其中三個(gè)作為主節(jié)點(diǎn)朵你,剩余三個(gè)分別作為其從節(jié)點(diǎn)各聘。對(duì)于這六份配置文件,以其中一份為例抡医,以下是其需要修改的參數(shù):
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"
對(duì)于其余的配置文件躲因,只需要將其中對(duì)應(yīng)項(xiàng)的端口號(hào)和帶有端口號(hào)的文件名修改為當(dāng)前要指定的端口號(hào)和端口號(hào)的文件名即可。配置文件配置好之后使用如下命令啟動(dòng)集群中的每個(gè)實(shí)例:
./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
仔細(xì)閱讀上述配置文件可發(fā)現(xiàn)忌傻,當(dāng)前配置和啟動(dòng)過(guò)程中并沒(méi)有指定這六個(gè)實(shí)例的主從關(guān)系大脉,也沒(méi)有對(duì)16384個(gè)槽位進(jìn)行分配。因而我們還需要進(jìn)行進(jìn)一步的配置芯勘,槽位的分配和主從關(guān)系的設(shè)定有兩種方式進(jìn)行箱靴,一種是使用redis-cli連接到集群節(jié)點(diǎn)上后使用cluster meet命令連接其他的節(jié)點(diǎn),如我們首先執(zhí)行如下命令連接到6379端口的節(jié)點(diǎn):
./src/redis-cli -p 6379
連接上后使用cluster meet命令分別連接其余節(jié)點(diǎn):
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命令查看當(dāng)前集群狀態(tài):
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
可以看到配置的六個(gè)節(jié)點(diǎn)都已經(jīng)加入到了集群中荷愕,但是其現(xiàn)在還不能使用衡怀,因?yàn)檫€沒(méi)有將16384個(gè)槽分配到集群節(jié)點(diǎn)中。虛擬槽的分配可以使用redis-cli分別連接到6379安疗,6380和6381端口的節(jié)點(diǎn)中抛杨,然后分別執(zhí)行如下命令:
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命令查看當(dāng)前集群狀態(tài):
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個(gè)虛擬槽位分配給了三個(gè)節(jié)點(diǎn),而剩余的三個(gè)節(jié)點(diǎn)我們通過(guò)如下命令將其配置為這三個(gè)節(jié)點(diǎn)的從節(jié)點(diǎn)荐类,從而達(dá)到高可用的目的:
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
如此怖现,所有的集群節(jié)點(diǎn)都配置完畢,并且處于可用狀態(tài)玉罐。這里可以使用cluster nodes命令查看當(dāng)前節(jié)點(diǎn)的狀態(tài):
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實(shí)例時(shí)需要加上參數(shù)-c屈嗤,表示連接的是集群模式的實(shí)例。連接上后執(zhí)行g(shù)et命令:
127.0.0.1:6380> get hello
-> Redirected to slot [866] located at 127.0.0.1:6379
(nil)
可以看到吊输,在6380端口的實(shí)例上執(zhí)行g(shù)et命令時(shí)饶号,其首先會(huì)為當(dāng)前的鍵通過(guò)一致哈希算法計(jì)算其所在的槽位,并且判斷該槽位不在當(dāng)前redis實(shí)例中季蚂,因而重定向到目標(biāo)實(shí)例上執(zhí)行該命令茫船,最后發(fā)現(xiàn)沒(méi)有該鍵對(duì)應(yīng)的值琅束,因而返回了一個(gè)(nil)。