redis 集群 分片 扩容_Redis高可用之集群实现原理
生活随笔
收集整理的這篇文章主要介紹了
redis 集群 分片 扩容_Redis高可用之集群实现原理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
概要:本文主要用于介紹Redis集群實現的原理,以及集群中的主從切換、副本漂移、分片遷移的原理
1
Redis集群實現的原理
集群是用來提供橫向擴展能力,即當數據量增多以后,通過增加服務節點就可以擴展服務能力。背后理論思想是將數據通過某種算法分布到不同的服務節點,這樣當節點越多,單臺節點所需提供的服務的數據就越少。要了解和使用集群,我們需要先解決以下問題。1.客戶端如何向集群發起請求(客戶端并不知道某個數據應該由那個節點提供服務,并且如果擴容或者節點故障后,不應該影響客戶端的訪問)?分槽(slot):即如何決定某條數據應該由那個節點提供服務;Redis將鍵空間分為了16384個slot,然后通過如下算法:HASH_SLOT = CRC16(key) mod 16384計算出每個key所屬的slot。客戶端可以請求任意一個節點,每個節點中都會保存所有16384個slot對應到哪一個節點的信息。如果一個key所屬的slot正好由被請求的節點提供服務,則直接處理并返回結果,否則返回MOVED重定向信息,如下:GET key -MOVED slot IP:PORT由-MOVED開頭,接著是該key計算出的slot,然后是該slot對應到的節點IP和PORT。客戶端接收并處理該重定向信息,并且向擁有該key的節點發起請求。在實際的應用中,Redis客戶端可以通過向集群請求slot和節點的映射關系并緩存,然后通過本地計算要操作的key所屬的slot,查找映射關系,直接向正確的節點發起請求,這樣可以獲得幾乎等價于單節點部署的性能。2.某個節點發生故障或擴容之后,該節點服務的數據該如何處理?當集群由于節點故障或者擴容導致重新分片,客戶端先通過重定向獲取到數據,每次發生重定向后,客戶端可以將新的映射關系進行緩存,下次仍然可以直接向正確的節點發起請求。3.同一條命令需要處理的key分布在不同的節點中,如何操作?集群架構中,每個主服務都會掛載至少一個從服務,當一條命令需要操作的key分屬于不同的節點時,Redis會報錯。Redis提供了一種稱之為hash tags的機制,由業務方保證當需要進行多個key的處理時,將所有key分布到同一個節點,該機制的原理如下:如果一個key包括{substring}這種模式,則計算slot時只計算"{"和"}"之間的子字符串。即keys{sub}1、keys{sub}2、keys{sub}3計算slot時都會按照sub串進行。這樣保證這3個字符串會分布到同一個節點。典型的Redis集群配置詳解配置如下:port 7001 // 監聽的端口cluster-enabled yes // 是否開啟集群模式cluster-config-file?nodes7001.conf???//?集群中該節點的配置文件cluster-node-timeout?5000???//?節點超時時間,超時之后會被認為故障daemonize?yes // 守護進程方式啟動節點可以直接使用redis-server命令啟動,如下:redis-server /path/redis-cluster.conf執行該命令后,redis-server會調用clusterInit函數進行加載配置文件和初始化。同時會執行以下一些回調函數的注冊:1)clusterAcceptHandler函數,當節點之間建立連接時先由該函數處理。2)clusterReadHandler函數,節點之間建立連接后,為新建立的連接注冊讀事件。3)當有讀事件發生時,即當clusterReadHandler讀取到一個完整的包體后,調用clusterProcessPacket解析具體的包數據。集群之間通信的數據包解析都是由該函數完成的。Redis時間任務函數serverCron會調度集群的周期性函數,serverCron () {if (server.cluster_enabled) clusterCron();?}其中clusterCron函數執行如下操作1)向其它節點發送MEET消息,將其加入集群。2)每1s隨機選擇一個節點,發送ping消息(心跳檢測)。3)如果一個節點在超時時間內仍未收到ping包的響應,則將其標記為pfail。4)檢查是否需要進行主從切換,如果需要則執行切換。5)檢查是否需要進行副本漂移,如果需要則執行。注意:Redis集群中節點的故障狀態有兩種。一種為pfail(Possible failure),當一個節點A未在指定時間收到另一個節點B對ping包的響應時,A節點會將B節點標記為pfail。另一種是,當大多數Master節點確認B為pfail之后,就會將B標記為fail。fail狀態的節點才需要執行主從切換。Redis除了在serverCron函數中進行調度之外,在每次進入事件循環之前,會在beforeSleep函數中執行一些操作:beforeSleep () {??if?(server.cluster_enabled)?clusterBeforeSleep();}clusterBeforeSleep函數會執行以下操作:1)檢查主從切換狀態,如果需要,執行主從切換相關操作。2)更新集群狀態,通過檢查是否所有slot都有相應的節點提供服務以及是否大部分主服務都是可用狀態,來決定集群處于正常狀態還是失敗狀態。3)刷新集群狀態到配置文件。2
集群中的主從切換
集群中的主從切換有兩種方式,自動和手動。1. 自動切換集群之間會互相發送心跳包,心跳包中會包括從發送方視角所記錄的關于其它節點的狀態信息。當一個節點收到心跳包之后,如果檢測到發送發A標記為某個節點B處于pfail狀態,則接收節點C會檢測B是否已經被大多數節點標記為pfail狀態,如果是,則C節點會向集群中所有節點發送一個fail包,通知其它節點B已處于fail狀態。當一個主節點(假設B)被標記為fail狀態后,該主節點的所有Slave執行周期性函數clusterCron時,會從所有的Slave中選擇一個復制偏移量最大的Slave節點(即數據最新的從節點,假設為D),然后D節點首先將其當前紀元(currentEpoch)加1,然后向所有的主節點發送failover授權請求包,當獲得大多數主節點授權后,開始執行主從切換。切換步驟如下(假設被切換的主節點為M,執行切換的從節點為S):1)S先更新自己的狀態,將自己聲明為主節點。并且將S從M中移除。2)由于S需要切換為主節點,所以將S的同步數據相關信息清楚(即不再從M同步數據)。3)將M提供服務的slot都聲明到S中。4)發送一個PONG包,通知集群中其它節點更新狀態。2. 手動切換優點:通過手動切換方式能實現Redis主節點的平滑升級,具體步驟是,先將主節點切換為一個從節點,然后進行版本升級,再將升級后的版本切換回主節點。該過程不會有任務服務的中斷。切換命令:cluster failover當一個從節點接收到該命令后,執行切換的流程如下:1)該從節點首先向對應的主節點發送一個mfstart包,通知主節點從節點要開始進行手動切換。2)主節點阻塞所有客戶端命令的執行。之后主節點在周期性函數clusterCron中發送ping包時會在包頭部分做特殊標記。3)當從節點收到主節點的ping包并且檢測到特殊標記之后,會從包頭中獲取主節點的復制偏移量。4)從節點在周期性函數clusterCron中檢測當前處理的偏移量與主節點夫hi偏移量是否相等,當相等時開始執行切換流程。5)切換完成后,主節點會將阻塞的所有客戶端命令通過發送+MOVED指令重定向到新的主節點。3
副本漂移
Redis中的副本漂移主要為了均衡高可用性和集群規模線性增長,即利用最少的實例達到更高的可靠性。架構描述:假設集群架構如下圖所示,我們只給其中一個主C增加兩個從服務,假設A發生故障,主A的從A1會執行切換,切換完成之后A1變為主A1,此時A1出現單點問題,當檢測到該單點問題后,集群會主動從主C的從服務中漂移一個給單點問題的主A1做從服務。實現副本漂移的條件:1)檢測是否存在單點的主節點。2)檢測是否存在兩臺及以上可用從節點的主節點。副本漂移的過程:1)從C的記錄中將C1移除。2)將C1所記錄的主節點更改為A1。3)在A1中添加C1為從節點。4)將C1的數據同步源設置為A1。4
分片遷移
在實際應用中很多情況下需要進行分片遷移。例如增加一個新節點之后需要把一些分片遷移到新節點,或者當刪除一個節點之后,需要該節點提供服務的分片遷移到其它節點,甚至有些時候需要根據負載重新配置分片的分布。下面,我們以一個例子來說明分片遷移的過程。假設slot中10000現在由A提供服務,需要將slot從A遷移到B。cluster?serslot?10000?importing?A??//?在B點執行cluster serslot 10000 migrating B // 在A點執行當客戶端請求屬于slot 10000的key時,仍然會直接向A發送請求,如果A中找到該key,則直接處理并返回結果。如果A中未找到該key,則返回如下信息:GET key-ASK 10000 B客戶端收到該回復后,首先需要向B發送一條asking命令,然后將要執行的命令發送給B。生產環境中使用Redis提供的redis-cli命令來做分片遷移,redis-cli首先在A、B節點執行如上兩條命令,然后在A節點執行如下命令:cluster getkeysinslot slot count這條命令會從節點A的slot,例如10000中取出count個key,然后對這些key依次執行遷移命令,如下:migrate?target_tp?target_port key 0 timeouttarget_ip和target_port指向B節點,0未數據庫ID(集群中的的所有節點只能有0號數據庫)。當所有keydou遷移完成后,redis-cli會向所有集群中的節點發送如下命令:cluster?serslot slot node node-id其中slot本例中為10000,node-id為B。至此,一個slot遷移完畢。當詞是再向A節點發送slot為10000的請求時,A節點會直接返回MOVED重定向到B節點。End
總結
本文首先引出集群中需要解決的幾個問題,然后具體介紹了Redis集群如何解決這些問題。主要介紹了Redis集群中如何實現主從切換,副本漂移的原理,以及分片遷移的具體思路。總結
以上是生活随笔為你收集整理的redis 集群 分片 扩容_Redis高可用之集群实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python输入什么就输出什么_一文读懂
- 下一篇: postgresql 创建用户_国内源安