<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
主從和哨兵可以解決高可用、高並行讀的問題。但是依然有兩個問題沒有解決:
針對上述問題,我們可以搭建Redis的分片叢集,如圖所示:
Redis的分片叢集具有以下特徵:
接下來我們可以動手來搭建一個Redis分片叢集
分片叢集需要的節點數量較多,這裡我們搭建一個最小的分片叢集,包含3個master節點,每個master包含一個slave節點,結構如下:
這裡我們會在同一臺虛擬機器器中開啟6個redis範例,模擬分片叢集,資訊如下:
IP | PORT | 角色 |
---|---|---|
192.168.211.100 | 7001 | master |
192.168.211.100 | 7002 | master |
192.168.211.100 | 7003 | master |
192.168.211.100 | 8001 | slave |
192.168.211.100 | 8002 | slave |
192.168.211.100 | 8003 | slave |
這裡我的redis安裝目錄為/usr/local/redis-6.2.6,以下操作將以此目錄進行參考,額外需要注意的是,以下操作都是在redis沒有設定密碼的情況下進行的,如果你的redis設定了密碼,那麼按照以下步驟進行就會出問題。
1)建立出7001、7002、7003、8001、8002、8003目錄
# 進入/local目錄 cd /usr/local # 建立目錄 mkdir 7001 7002 7003 8001 8002 8003
2)在/usr/local下準備一個新的redis.conf檔案,內容如下:
port 6379 # 開啟叢集功能 cluster-enabled yes # 叢集的組態檔名稱,不需要我們建立,由redis自己維護 cluster-config-file /usr/local/6379/nodes.conf # 節點心跳失敗的超時時間 cluster-node-timeout 5000 # 持久化檔案存放目錄 dir /usr/local/6379 # 繫結地址 bind 0.0.0.0 # 讓redis後臺執行 daemonize yes # 註冊的範例ip replica-announce-ip 192.168.211.100 # 保護模式 protected-mode no # 資料庫數量 databases 1 # 紀錄檔 logfile /usr/local/6379/run.log
3)將這個檔案拷貝到每個目錄下:
# 進入/local目錄 cd /usr/local # 執行拷貝 echo 7001 7002 7003 8001 8002 8003 | xargs -t -n 1 cp redis.conf
4)修改每個目錄下的redis.conf,將其中的6379修改為與所在目錄一致:
# 進入/local目錄 cd /usr/local # 修改組態檔 printf '%sn' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf
因為已經設定了後臺啟動模式,所以可以直接啟動服務:
# 進入/usr/local目錄 cd /usr/local # 一鍵啟動所有服務 printf '%sn' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-server {}/redis.conf
通過ps檢視狀態:
ps -ef | grep redis
發現服務都已經正常啟動:
如果要關閉所有程序,可以執行命令:
ps -ef | grep redis | awk '{print $2}' | xargs kill
或者(推薦這種方式):
printf '%sn' 7001 7002 7003 8001 8002 8003 | xargs -I{<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->} -t redis-cli -p {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->} shutdown
雖然服務啟動了,但是目前每個服務之間都是獨立的,沒有任何關聯。我們需要執行以下命令來建立叢集,注意,以下命令需要你的redis版本在5.0之後:
redis-cli --cluster create --cluster-replicas 1 192.168.211.100:7001 192.168.211.100:7002 192.168.211.100:7003 192.168.211.100:8001 192.168.211.100:8002 192.168.211.100:8003
命令說明:
redis-cli --cluster
:代表叢集操作命令create
:代表建立叢集--cluster-replicas 1
:指定叢集中每個master的副本個數為1,也就是說一個master只有一個slave,此時節點總數 ÷ (replicas + 1)
得到的就是master的數量。因此節點列表中的前n個就是master,其它節點都是slave節點,在建立叢集時這些slave會被隨機分配給不同master執行上述命令之後,控制檯會列出當前主從節點分配的結果,即將那些slave分別分配給哪些master,並詢問你是否同意,這裡我們輸入'yes'
即可
確定之後,叢集開始建立
通過命令可以檢視叢集狀態:
redis-cli -p 7001 cluster nodes
叢集操作時,需要在redis-cli連線時帶上-c引數才可以
redis-cli -p 7001
通過觀察上述從節點的狀態,我們發現7001的slave是8001,我們可以嘗試在7001裡插入一個數位,再從8001裡獲取
事實上,我們不僅可以從8001裡獲取到num,也可以從其他slave甚至其他master裡獲取到num:
而且我們發現,當我們試圖從其他節點獲取num時,最後都會跳轉到7001,為什麼會這樣呢?這就涉及到我們即將講解的插槽原理
一個Redis分片叢集有0~16383共16384個插槽(hash slot),這些插槽會被平均分給每一個master節點,一個master節點對映著一部分插槽,這一點在叢集建立時的資訊中可以看到
在分片叢集中,資料key並不是與某個節點繫結,而是與插槽繫結。資料key與插槽是多對一的關係,redis會根據key的有效部分計算插槽值,然後將key放入對應插槽,key的有效部分分兩種情況:
舉個例子,假如key是num,那麼插槽值就會根據num來計算,如果key是{itheima}num,那麼插槽值就會根據itheima來計算。計算方式是利用CRC16演演算法得到一個hash值,然後對16384取餘,得到的結果就是slot值。
如果當前操作的key所在的插槽不屬於本節點,則會發生重定向,重定向的目標是該插槽所屬的節點,這個節點一定是master,如果我們連線的節點為slave,則會直接進行重定向,因為slave是沒有插槽的。
針對上述幾點,演示如下:
如上圖所示,我們連線了7001,並試圖插入資料k1,這時redis需要去判斷k1所屬的插槽位置,由於key中不包含’{}',因此整個key都是有效部分,redis會對k1做hash運算然後對16384取餘,得到的結果是12706,這也就是k1所在的插槽的位置,在當前叢集中,對映該插槽的節點是7003,此時就會發生重定向,我們也可以觀察到當我們執行完set k1 1
命令之後,操作的埠已經變成了7003。此時我們繼續在7003埠中進行操作,比如修改資料num的值,而num所在的插槽是2765,在當前叢集中,對映該插槽的節點是7001,因此當我們執行完set num 2
命令之後,操作的埠又重新變成了7001
那麼接下來讓我們思考兩個問題:
為什麼資料key要與插槽繫結,而不是與節點繫結呢?
這是因為Redis的主節點有可能會出現宕機情況,也有可能由於叢集伸縮而被刪除,當節點刪除或者發生宕機時,節點上儲存的資料也就丟失了,但如果資料繫結的是插槽而不是節點,那麼當出現上述情況時,就可以將故障節點的插槽轉移至存活節點上。這樣,資料跟插槽繫結,就永遠都能夠找到資料所在位置。
如何將同一類資料固定的儲存在一個插槽中
在業務開發中,同一型別的資料key最好是儲存在一個插槽中,因為如果分散儲存,在我們呼叫的時候就很可能出現重定向的情況,重定向是會消耗一部分效能的。如果我們希望將同一型別的資料key最好是儲存在一個插槽中,可以為這些key帶上一個用’{}'包裹的固定字首,比如{user}zs、{user}ls等等,因為我們之前說過,當key中包含"{}“,且”{}“中至少包含1個字元時,”{}"中的部分是有效部分,redis會根據這一部分來計算插槽值,如果我們將同一型別的key都加上這類字首,就能保證這些key在同一個插槽中了
叢集已經建立了,那麼如果我們想在叢集中新增節點或刪除節點,又應該怎麼做呢?
redis-cli --cluster
提供了很多操作叢集的命令,可以通過下面方式檢視:
其中就包括新增節點的命令:
假設現在有以下需求:向叢集中新增一個新的master節點7004,並在這個節點中儲存 num = 10,執行步驟如下:
1)在/usr/local目錄下建立一個資料夾:
cd /usr/local mkdir 7004
2)拷貝組態檔:
cp redis.conf 7004
3)修改組態檔:
printf '%sn' 7004 | xargs -I{<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->} -t sed -i 's/6379/{}/g' {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->}/redis.conf
4)啟動
redis-server 7004/redis.conf
接下來就需要將7004新增到叢集中了,在執行新增操作之前,我們先來了解以下新增節點的命令
新增節點首先需要以下幾個引數:
new_host:new_port
:指定新新增的節點的ip地址與埠號,這個沒什麼好說的existing_host:existing_port
:任意指定一個叢集中已經存在的節點的ip地址與埠號。因為叢集中加入新節點是需要通知其他舊節點的,新節點只需要將自己的資訊提供給叢集中任意一個節點,那麼整個叢集就都能知道關於新節點的資訊了cluster-slave
:可選項,不指定則表示該節點是master,如果指定了則表示該節點是一個slavecluster-master-id <arg>
:如果我們指定了cluster-slave,那麼就需要通過該引數指定該節點的master的id瞭解了該命令之後,接下來我們來執行新增節點操作:
執行命令:
redis-cli --cluster add-node 192.168.211.100:7004 192.168.211.100:7001
通過命令檢視叢集狀態:
redis-cli -p 7001 cluster nodes
如圖,7004加入了叢集,並且預設是一個master節點:
但是,我們也可以看到7004是沒有插槽的,因為插槽已經被其他master瓜分完畢了,因此沒有任何資料可以儲存到7004上,這時候我們就需要進行插槽的轉移,即將其他matser的插槽分出一部分給7004
首先回歸需求本身,我們的需求是將num=10儲存在7004節點上,那麼我們的目的就很明顯了,首先需要知道num儲存在哪個插槽上,然後將這個插槽轉移到7004上即可
如上圖所示,num的插槽為2765,該插槽目前是儲存在7001上的,因此我們可以將0~3000的插槽從7001轉移到7004,轉移插槽的命令格式如下:
具體步驟如下:
1)輸入轉移插槽命令,這裡我們需要轉移的插槽在7001上,因此需要指定7001的地址
redis-cli --cluster reshard 192.168.211.100:7001
2)系統會詢問我們要移動多少個插槽,這裡我們輸入3000即可
3)系統接著詢問我們需要讓哪個節點來接收插槽,這裡我們需要輸入7004的ID
4)接著系統會詢問我們要從哪些節點中移動這些插槽到7004
這裡我們有三個選擇:
這裡我們需要從7001中獲取插槽,因此填寫7001的id,然後輸入done表示結束
5)接下來會冒出一大串東西,並詢問我們是否確定要移動這些插槽,這裡我們直接輸入yes即可
輸入yes之後,等待控制檯列印結束,插槽也就移動完畢了
6) 輸入以下命令檢視插槽是否已經移動到7004
redis-cli -p 7001 cluster nodes
很顯然,我們的目的已經達成了
那麼如果我們要刪除7004節點,又應該怎樣做呢?這裡筆者只給去具體思路,大家可以自行嘗試一下:
redis-cli --cluster del-node host:port node_id
redis-cli -p 7001 cluster nodes
之前我們提到過,redis分片叢集可以通過master之間的心跳監測來監測彼此之間的健康狀態,從而取代哨兵。而我們也知道,哨兵的作用就是監測master和slave的狀態,當認為一個master客觀下線後,會從slave中選舉出一個新的master,現在讓我們來驗證一下redis分片叢集是否具備這個功能。
首先叢集的初始狀態是這樣的,如果狀態為connected則表示節點正常連線
其中7001、7002、7003、7004都是master,我們計劃讓7002宕機。
當叢集中有一個master宕機會發生什麼呢?我們可以直接停止一個redis範例,例如7002:
redis-cli -p 7002 shutdown
1)首先是該範例與其它範例失去連線
2)然後是疑似宕機,7002的狀態變成了disconnected
3)最後是確定下線,將7002的一個slave提升為新的master,這裡由於7002只有一個slave,即8002,因此8002被選為了新的master
4)接下來我們通過以下命令再次啟動7002節點
redis-server /usr/local/7002/redis.conf
當7002再次啟動之後,它就已經變為一個slave節點了
上面這種叫自動故障轉移,但有的時候我們可能需要做手動故障轉移,比如當某臺master機器比較老舊,需要升級時,我們就可以在這個叢集中新增一個節點,讓這個節點成為取代原來的master成為新的master,這樣原來的master就會變成新master的一個slave,從而實現機器的無感知升級
我們可以在slave節點中使用cluster failover命令,這個命令會讓當前slave節點的master暫時宕機,宕機期間會將自身的資料轉移給執行命令的slave節點,宕機結束後,之前的master會變成slave,而執行命令的slave會變成新的master。
其詳細流程如下:
當slave執行了cluster failover命令之後,就會向master節點傳送節點替換通知,為了避免資料的丟失,master接收到slave節點傳送過來的通知後,就會暫時拒絕來自使用者端的任何資料讀寫請求。然後,master會將自己當前的offset返回給slave,slave接收到後會判斷自身資料中的offset與master的offset是否一致,如果不一致,則需要進行資料同步。由於 master 已經拒絕了使用者端的所有請求,那麼一旦 slave完成資料同步,也就表示slave與master之間資料是完全一致的。
資料同步結束之後,就會開始進行故障轉移,讓slave與master 進行角色互換,該slave成為新的master,而舊的master則轉變為一個新的slave。轉移結束後,slave便會標記自己為master,並向叢集中每一個節點廣播故障轉移的結果。當叢集中節點收到廣播後,後續的所有互動便轉移至新的master。
這種failover命令可以指定三種模式:
預設:預設的流程,如圖1~6歩,一般我們會選擇這個force:省略了對offset的一致性校驗,直接開始故障轉移takeover:直接執行第5歩,忽略資料一致性、忽略master狀態和其它master的意見
接下來我們可以嘗試一下,在7002這個slave節點上執行手動故障轉移,讓它重新奪回master地位,步驟如下:
1)利用redis-cli連線7002,並執行cluster failover命令
2)通過redis-cli -p 7001 cluster nodes
命令檢視節點狀態
我們只需要通過以下簡單的設定,就可以通過Java程式碼存取我們之前部署好的分片叢集
1)在boot專案的pom檔案中匯入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
2)在application.yml中指定sentinel相關資訊:
spring: redis: cluster: nodes: #指定分片叢集中每一個節點資訊 - 192.168.150.101:7001 - 192.168.150.101:7002 - 192.168.150.101:7003 - 192.168.150.101:8001 - 192.168.150.101:8002 - 192.168.150.101:8003
3)在專案的啟動類中,新增一個新的bean,這個bean是用來做Redis叢集的讀寫分離的
@Bean public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){ return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED); }
bean中設定的資訊是讀寫策略,包括四種可選項:
上述設定完畢之後,我們就可以正常使用RedisTemplate來對redis叢集進行操作,如果叢集中某個的master宕機了,叢集就會自動選舉新的master,並將新master的資訊傳送給該Java程式,這樣Java程式就可以對新master進行寫操作而對其他節點進行讀操作了。而這一過程都是自動完成的,無需我們過多關注
到此這篇關於Redis 分片叢集的實現的文章就介紹到這了,更多相關Redis 分片叢集內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45