詳解三分鐘快速搭建分布式高可用的Redis集群
這里的Redis集群指的是Redis Cluster,它是Redis在3.0版本正式推出的專(zhuān)用集群方案,有效地解決了Redis分布式方面的需求。當(dāng)單機(jī)內(nèi)存、并發(fā)、流量等遇到瓶頸的時(shí)候,可以采用這種Redis Cluster方案進(jìn)行解決。
分區(qū)規(guī)則
Redis Cluster采用虛擬槽(slot)進(jìn)行數(shù)據(jù)分區(qū),即使用分散度良好的哈希函數(shù)把所有鍵映射到一個(gè)固定范圍的整數(shù)集合里,這里的整數(shù)就是槽(slot)。Redis Cluster槽的范圍是0~16383,計(jì)算公式:slot=CRC16(key) & 16383。
白嫖小貼士:CRC16是一種高質(zhì)量的哈希算法,可以使每個(gè)槽所映射的鍵通常比較均勻。
當(dāng)集群中有3個(gè)節(jié)點(diǎn)時(shí),每個(gè)節(jié)點(diǎn)平均大概負(fù)責(zé)5461個(gè)槽以及槽所映射的鍵值數(shù)據(jù)。這樣一來(lái),可以解耦數(shù)據(jù)與節(jié)點(diǎn)之間的關(guān)系,簡(jiǎn)化節(jié)點(diǎn)擴(kuò)容和縮容的難度。節(jié)點(diǎn)自身維護(hù)槽的映射關(guān)系,不需要客戶(hù)端或代理服務(wù)維護(hù)分區(qū)信息。
不過(guò),Redis Cluster相對(duì)于單機(jī)還是存在一些限制的,比如:
- 批量操作鍵支持有限,僅支持具有相同槽的鍵進(jìn)行批量操作。
- 事務(wù)操作鍵支持有限,僅支持在同一個(gè)節(jié)點(diǎn)上多個(gè)鍵的事務(wù)操作。
- 不支持多個(gè)數(shù)據(jù)空間。單機(jī)Redis可以支持16個(gè)數(shù)據(jù)庫(kù),而Cluster模式下只能使用一個(gè)數(shù)據(jù)庫(kù)空間。
扯了這么多Redis Cluster的分區(qū)規(guī)則,下面我們開(kāi)始步入正題。
手動(dòng)搭建
把Redis Cluster搭建起來(lái)總共幾步?答:三步!第一步把冰箱門(mén)打開(kāi)。第二步把大象關(guān)進(jìn)去。第三步把冰箱門(mén)帶上。不好意思,段子暴露年齡了。集群搭建需要以下三個(gè)步驟:
- 準(zhǔn)備節(jié)點(diǎn)。
- 節(jié)點(diǎn)握手。
- 分配槽。
Redis Cluster由多個(gè)節(jié)點(diǎn)組成,節(jié)點(diǎn)數(shù)量至少有6個(gè)才能組成一個(gè)完整高可用的集群,其中有3個(gè)主節(jié)點(diǎn)和3個(gè)從節(jié)點(diǎn),我們就以此為例搭建一個(gè)Redis Cluster。
準(zhǔn)備節(jié)點(diǎn)
首先,為6個(gè)節(jié)點(diǎn)(同一臺(tái)機(jī)器上的6380、6381、6382、6383、6384、6385端口)分別創(chuàng)建配置文件,以6380端口的節(jié)點(diǎn)為例:
# 節(jié)點(diǎn)端口 port 6380 #日志文件 logfile "log/redis-6380.log" # 開(kāi)啟集群模式 cluster-enabled yes # 集群配置文件 cluster-config-file "data/nodes-6380.conf"
保持文件名為redis-6380.conf,其他節(jié)點(diǎn)的配置文件替換成各自的端口。準(zhǔn)備好配置文件后啟動(dòng)所有節(jié)點(diǎn),命令如下:
src/redis-server conf/redis-6380.conf & src/redis-server conf/redis-6381.conf & src/redis-server conf/redis-6382.conf & src/redis-server conf/redis-6383.conf & src/redis-server conf/redis-6384.conf & src/redis-server conf/redis-6385.conf &
檢測(cè)日志是否正確,以下是6380端口的節(jié)點(diǎn)的日志:
# oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo # Redis version=4.0.14, bits=64, commit=00000000, modified=0, pid=3031, just started # Configuration loaded * No cluster configuration found, I'm df1ac987f47dea35f1d0a83c3b405f0ef86892ab * Running mode=cluster, port=6380.
6380端口的節(jié)點(diǎn)啟動(dòng)成功,第一次啟動(dòng)時(shí)如果沒(méi)有集群配置文件,Redis會(huì)自動(dòng)創(chuàng)建一個(gè)。6380端口的節(jié)點(diǎn)創(chuàng)建的集群配置文件如下:
df1ac987f47dea35f1d0a83c3b405f0ef86892ab :0@0 myself,master - 0 0 0 connected vars currentEpoch 0 lastVoteEpoch 0
集群文件中記錄的集群的狀態(tài),這里最重要的是節(jié)點(diǎn)ID,它是一個(gè)40位的16進(jìn)制字符串,用于唯一標(biāo)識(shí)集群中的這個(gè)節(jié)點(diǎn)。同樣,也可以通過(guò)cluster nodes命令查看集群節(jié)點(diǎn)狀態(tài)。比如在6380端口的節(jié)點(diǎn)上執(zhí)行命令:
127.0.0.1:6380> cluster nodes df1ac987f47dea35f1d0a83c3b405f0ef86892ab :6380@16380 myself,master - 0 0 0 connected
目前,我們已經(jīng)成功啟動(dòng)了6個(gè)節(jié)點(diǎn),但是它們只能識(shí)別自己的節(jié)點(diǎn)信息,互相之間并不認(rèn)識(shí)。下面我們通過(guò)節(jié)點(diǎn)握手讓這6個(gè)節(jié)點(diǎn)互相之間建立聯(lián)系從而組成一個(gè)集群。
節(jié)點(diǎn)握手
節(jié)點(diǎn)握手是一些運(yùn)行在集群模式下的節(jié)點(diǎn)通過(guò)Gossip協(xié)議互相通信,達(dá)到感知彼此的過(guò)程。
白嫖小貼士:Gossip協(xié)議是基于流行病傳播方式的節(jié)點(diǎn)或者進(jìn)程之間信息交換的協(xié)議,在分布式系統(tǒng)中被廣泛使用。
節(jié)點(diǎn)握手通過(guò)客戶(hù)端執(zhí)行cluster meet命令實(shí)現(xiàn),它是一個(gè)異步命令,執(zhí)行之后立刻返回,在Redis內(nèi)部異步發(fā)起與目標(biāo)節(jié)點(diǎn)的握手通信,該命令的語(yǔ)法如下:
cluster meet 目標(biāo)節(jié)點(diǎn)IP 目標(biāo)節(jié)點(diǎn)端口
把6個(gè)節(jié)點(diǎn)加到一個(gè)集群中:
127.0.0.1:6380> cluster meet 127.0.0.1 6381 OK 127.0.0.1:6380> cluster meet 127.0.0.1 6382 OK 127.0.0.1:6380> cluster meet 127.0.0.1 6383 OK 127.0.0.1:6380> cluster meet 127.0.0.1 6384 OK 127.0.0.1:6380> cluster meet 127.0.0.1 6385 OK
只需要在集群中任意節(jié)點(diǎn)上執(zhí)行cluster meet命令加入新的節(jié)點(diǎn),握手狀態(tài)會(huì)通過(guò)消息在集群中傳播,其他節(jié)點(diǎn)也會(huì)自動(dòng)發(fā)現(xiàn)新節(jié)點(diǎn)并與之發(fā)起握手流程。
我們?cè)賵?zhí)行一下cluster nodes命令,檢查一下6個(gè)節(jié)點(diǎn)是否已經(jīng)組成集群:
127.0.0.1:6380> cluster nodes 1e1f45677d7b9b0130d03193f0bcec34578ac47d 127.0.0.1:6385@16385 master - 0 1586617919021 5 connected df1ac987f47dea35f1d0a83c3b405f0ef86892ab 127.0.0.1:6380@16380 myself,master - 0 1586617916000 2 connected 5846b66ebe4fb4a5dcfd035652cc471f7e412752 127.0.0.1:6381@16381 master - 0 1586617917005 1 connected a435cf98c3444b0b110a224401e397a107c453ef 127.0.0.1:6384@16384 master - 0 1586617914988 4 connected 71e0e9e9a6f0c7c85dbe0d396846a9072625c5e8 127.0.0.1:6383@16383 master - 0 1586617918013 3 connected e25590603c7a254cce43aa8437861c5c425d753d 127.0.0.1:6382@16382 master - 0 1586617916000 0 connected
可以看到,6個(gè)節(jié)點(diǎn)都在集群中了。不過(guò),此時(shí)因?yàn)檫€沒(méi)有為集群中的節(jié)點(diǎn)分配槽,集群還處于下線(xiàn)狀態(tài),所有的數(shù)據(jù)讀寫(xiě)都是被禁止的。比如:
127.0.0.1:6380> set onemore study (error) CLUSTERDOWN Hash slot not served
接下來(lái),我們?yōu)榧褐械墓?jié)點(diǎn)分配槽。
分配槽
我們把6380、6382、6384端口的節(jié)點(diǎn)作為主節(jié)點(diǎn),負(fù)責(zé)處理槽和相關(guān)數(shù)據(jù);6381、6383、6385端口的節(jié)點(diǎn)分別作為從節(jié)點(diǎn),負(fù)責(zé)故障轉(zhuǎn)移。先把16384個(gè)槽平均分配給6380、6382、6384端口的節(jié)點(diǎn),為節(jié)點(diǎn)分配槽是通過(guò)cluster addslots命令實(shí)現(xiàn):
# ./redis-cli -h 127.0.0.1 -p 6380 cluster addslots {0..5461} OK # ./redis-cli -h 127.0.0.1 -p 6382 cluster addslots {5462..10922} OK # ./redis-cli -h 127.0.0.1 -p 6384 cluster addslots {10923..16383} OK
我們?cè)賵?zhí)行一下cluster nodes命令,檢查一下槽是否已經(jīng)分配:
127.0.0.1:6380> cluster nodes 1e1f45677d7b9b0130d03193f0bcec34578ac47d 127.0.0.1:6385@16385 master - 0 1586619468000 5 connected df1ac987f47dea35f1d0a83c3b405f0ef86892ab 127.0.0.1:6380@16380 myself,master - 0 1586619464000 2 connected 0-5461 5846b66ebe4fb4a5dcfd035652cc471f7e412752 127.0.0.1:6381@16381 master - 0 1586619467000 1 connected a435cf98c3444b0b110a224401e397a107c453ef 127.0.0.1:6384@16384 master - 0 1586619467000 4 connected 10923-16383 71e0e9e9a6f0c7c85dbe0d396846a9072625c5e8 127.0.0.1:6383@16383 master - 0 1586619467348 3 connected e25590603c7a254cce43aa8437861c5c425d753d 127.0.0.1:6382@16382 master - 0 1586619468355 0 connected 5462-10922
再使用cluster replicate命令把一個(gè)節(jié)點(diǎn)變成從節(jié)點(diǎn).,這個(gè)命令必須在從節(jié)點(diǎn)上運(yùn)行,它的語(yǔ)法是:
cluster replicate 主節(jié)點(diǎn)ID
把6381、6383、6385端口的節(jié)點(diǎn)變成對(duì)應(yīng)6380、6382、6384端口的節(jié)點(diǎn)的從節(jié)點(diǎn):
# ./redis-cli -h 127.0.0.1 -p 6381 127.0.0.1:6381> cluster replicate df1ac987f47dea35f1d0a83c3b405f0ef86892ab OK 127.0.0.1:6381> exit # ./redis-cli -h 127.0.0.1 -p 6383 127.0.0.1:6383> cluster replicate e25590603c7a254cce43aa8437861c5c425d753d OK 127.0.0.1:6383> exit # ./redis-cli -h 127.0.0.1 -p 6385 127.0.0.1:6385> cluster replicate a435cf98c3444b0b110a224401e397a107c453ef OK 127.0.0.1:6385> exit
我們?cè)賵?zhí)行一下cluster nodes命令,檢查一下集群狀態(tài)和主從關(guān)系:
127.0.0.1:6380> cluster nodes df1ac987f47dea35f1d0a83c3b405f0ef86892ab 127.0.0.1:6380@16380 myself,master - 0 1586620148000 2 connected 0-5461 5846b66ebe4fb4a5dcfd035652cc471f7e412752 127.0.0.1:6381@16381 slave df1ac987f47dea35f1d0a83c3b405f0ef86892ab 0 1586620150000 2 connected e25590603c7a254cce43aa8437861c5c425d753d 127.0.0.1:6382@16382 master - 0 1586620151000 0 connected 5462-10922 71e0e9e9a6f0c7c85dbe0d396846a9072625c5e8 127.0.0.1:6383@16383 slave e25590603c7a254cce43aa8437861c5c425d753d 0 1586620152220 3 connected a435cf98c3444b0b110a224401e397a107c453ef 127.0.0.1:6384@16384 master - 0 1586620150000 4 connected 10923-16383 1e1f45677d7b9b0130d03193f0bcec34578ac47d 127.0.0.1:6385@16385 slave a435cf98c3444b0b110a224401e397a107c453ef 0 1586620149000 5 connected
自此,RedisCluster已經(jīng)手動(dòng)搭建完成。手動(dòng)搭建可以理解集群建立的流程和細(xì)節(jié),不過(guò)大家也會(huì)發(fā)現(xiàn)手動(dòng)搭建有很多步驟,當(dāng)集群的節(jié)點(diǎn)比較多的時(shí)候,肯定會(huì)讓人頭大。所以Redis官方提供了redis-trib.rb工具,可以讓我們快速地搭建集群。
自動(dòng)搭建
redis-trib.rb是使用Ruby開(kāi)發(fā)的Redis Cluster的管理工具,不需要額外下載,默認(rèn)位于源碼包的src目錄下,但因?yàn)樵摴ぞ呤怯肦uby開(kāi)發(fā)的,所以需要準(zhǔn)備相關(guān)的依賴(lài)環(huán)境。
環(huán)境準(zhǔn)備
安裝Ruby:
yum -y install zlib-devel wget https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.1.tar.gz tar xvf ruby-2.5.1.tar.gz cd ruby-2.5.1/ ./configure -prefix=/usr/local/ruby make make install cd /usr/local/ruby/ cp bin/ruby /usr/local/bin cp bin/gem /usr/local/bin
安裝rubygem redis依賴(lài):
wget http://rubygems.org/downloads/redis-3.3.0.gem gem install -l redis-3.3.0.gem
安裝redis-trib.rb:
cp src/redis-trib.rb /usr/local/bin
執(zhí)行redis-trib.rb命令確認(rèn)一下環(huán)境是否準(zhǔn)備正確:
# redis-trib.rb help Usage: redis-trib <command> <options> <arguments ...> create host1:port1 ... hostN:portN --replicas <arg> check host:port info host:port fix host:port --timeout <arg> reshard host:port --from <arg> ...此處省略一萬(wàn)個(gè)字...
搭建集群
像前面的內(nèi)容講的,準(zhǔn)備好節(jié)點(diǎn)配置并啟動(dòng):
src/redis-server conf/redis-7380.conf & src/redis-server conf/redis-7381.conf & src/redis-server conf/redis-7382.conf & src/redis-server conf/redis-7383.conf & src/redis-server conf/redis-7384.conf & src/redis-server conf/redis-7385.conf &
使用redis-trib.rb create命令完成節(jié)點(diǎn)握手和槽分配的工作,命令如下:
redis-trib.rb create --replicas 1 127.0.0.1:7380 127.0.0.1:7382 127.0.0.1:7384 127.0.0.1:7381 127.0.0.1:7383 127.0.0.1:7385
其中--replicas參數(shù)用來(lái)指定集群中每個(gè)主節(jié)點(diǎn)有幾個(gè)從節(jié)點(diǎn),這里設(shè)置的是1。命令執(zhí)行后,會(huì)首先給出主從節(jié)點(diǎn)的分配計(jì)劃:
>>> Creating cluster >>> Performing hash slots allocation on 6 nodes... Using 3 masters: 127.0.0.1:7380 127.0.0.1:7382 127.0.0.1:7384 Adding replica 127.0.0.1:7383 to 127.0.0.1:7380 Adding replica 127.0.0.1:7385 to 127.0.0.1:7382 Adding replica 127.0.0.1:7381 to 127.0.0.1:7384 >>> Trying to optimize slaves allocation for anti-affinity [WARNING] Some slaves are in the same host as their master M: c25675d021c377c91f860986025e3779d89ede79 127.0.0.1:7380 slots:0-5460 (5461 slots) master M: 58980a81b49de31383802d7d21d6782881678922 127.0.0.1:7382 slots:5461-10922 (5462 slots) master M: 3f00a37d2c7a5ea40671c8f2934f66d059157a4a 127.0.0.1:7384 slots:10923-16383 (5461 slots) master S: 6f7dd93973a8332305831e6b7b5e2c54c15b3b51 127.0.0.1:7381 replicates 3f00a37d2c7a5ea40671c8f2934f66d059157a4a S: 03e01f82a935ed7f977af092e6a9cb71057df68a 127.0.0.1:7383 replicates c25675d021c377c91f860986025e3779d89ede79 S: 2cf3883e974a709b7070d6c4d7c528d9fa813358 127.0.0.1:7385 replicates 58980a81b49de31383802d7d21d6782881678922 Can I set the above configuration? (type 'yes' to accept):
如果我們同意這份計(jì)劃就輸入yes,之后就會(huì)開(kāi)始執(zhí)行節(jié)點(diǎn)握手和槽分配,輸入如下:
>>> 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:7380) M: c25675d021c377c91f860986025e3779d89ede79 127.0.0.1:7380 slots:0-5460 (5461 slots) master 1 additional replica(s) M: 58980a81b49de31383802d7d21d6782881678922 127.0.0.1:7382 slots:5461-10922 (5462 slots) master 1 additional replica(s) S: 2cf3883e974a709b7070d6c4d7c528d9fa813358 127.0.0.1:7385 slots: (0 slots) slave replicates 58980a81b49de31383802d7d21d6782881678922 S: 03e01f82a935ed7f977af092e6a9cb71057df68a 127.0.0.1:7383 slots: (0 slots) slave replicates c25675d021c377c91f860986025e3779d89ede79 S: 6f7dd93973a8332305831e6b7b5e2c54c15b3b51 127.0.0.1:7381 slots: (0 slots) slave replicates 3f00a37d2c7a5ea40671c8f2934f66d059157a4a M: 3f00a37d2c7a5ea40671c8f2934f66d059157a4a 127.0.0.1:7384 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.
集群創(chuàng)建完成后,還可以使用redis-trib.rb check命令檢查集群是否創(chuàng)建成功,具體命令如下:
# redis-trib.rb check 127.0.0.1:7380 >>> Performing Cluster Check (using node 127.0.0.1:7380) M: c25675d021c377c91f860986025e3779d89ede79 127.0.0.1:7380 slots:0-5460 (5461 slots) master 1 additional replica(s) M: 58980a81b49de31383802d7d21d6782881678922 127.0.0.1:7382 slots:5461-10922 (5462 slots) master 1 additional replica(s) S: 2cf3883e974a709b7070d6c4d7c528d9fa813358 127.0.0.1:7385 slots: (0 slots) slave replicates 58980a81b49de31383802d7d21d6782881678922 S: 03e01f82a935ed7f977af092e6a9cb71057df68a 127.0.0.1:7383 slots: (0 slots) slave replicates c25675d021c377c91f860986025e3779d89ede79 S: 6f7dd93973a8332305831e6b7b5e2c54c15b3b51 127.0.0.1:7381 slots: (0 slots) slave replicates 3f00a37d2c7a5ea40671c8f2934f66d059157a4a M: 3f00a37d2c7a5ea40671c8f2934f66d059157a4a 127.0.0.1:7384 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.
可以看到,所有的槽都已分配到節(jié)點(diǎn)上,大功告成!
到此這篇關(guān)于詳解三分鐘快速搭建分布式高可用的Redis集群的文章就介紹到這了,更多相關(guān)Redis搭建分布式高可用集群內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Redis+PHP實(shí)現(xiàn)用戶(hù)消息推送每天最多通知2次的功能
在開(kāi)發(fā)應(yīng)用程序中,經(jīng)常需要向用戶(hù)推送消息通知,但是為了避免過(guò)多的打擾用戶(hù),我們希望限制每天最多通知2次,本篇博文將介紹如何使用PHP和Redis實(shí)現(xiàn)這一功能,文中有詳細(xì)的代碼示例,需要的朋友可以參考下2023-10-10redis中token失效引發(fā)的一次生產(chǎn)事故
項(xiàng)目再測(cè)試的時(shí)候發(fā)現(xiàn)不定時(shí)token失效,本文主要介紹了redis中token失效引發(fā)的一次生產(chǎn)事故,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-03-03Redis GEO實(shí)現(xiàn)搜索附近用戶(hù)的項(xiàng)目實(shí)踐
RedisGEO主要用于存儲(chǔ)地理位置信息,并對(duì)存儲(chǔ)的信息進(jìn)行操作,本文主要介紹了Redis GEO實(shí)現(xiàn)搜索附近用戶(hù)的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下2024-05-05Redisson實(shí)現(xiàn)分布式鎖、鎖續(xù)約的案例
這篇文章主要介紹了Redisson如何實(shí)現(xiàn)分布式鎖、鎖續(xù)約,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03redis樂(lè)觀鎖與悲觀鎖的實(shí)戰(zhàn)?
Redis提供了兩種鎖機(jī)制,即樂(lè)觀鎖和悲觀鎖。本文主要介紹了redis樂(lè)觀鎖與悲觀鎖的實(shí)戰(zhàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04Redis主從復(fù)制與讀寫(xiě)分離的實(shí)現(xiàn)
Redis在作為緩存的時(shí)候,隨著項(xiàng)目訪問(wèn)量的增加,對(duì)Redis服務(wù)器的操作也越加頻繁,雖然Redis讀寫(xiě)速度都很快,但是一定程度上也會(huì)造成一定的延時(shí),本文主要介紹了Redis主從復(fù)制與讀寫(xiě)分離的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12