Redis系列 - 主從庫模式、哨兵和分片集群

2021-02-07 泉城IT圈子
主從庫模式

Redis的高可靠性主要包括兩方面:

數據儘量少丟失:RDB & AOF機制

服務儘量少中斷:增加副本冗餘

主從模式

Redis提供了主從庫模式,增加冗餘的副本來提高Redis集群的高可靠性。主從庫之間採用讀寫分離的方式,寫請求只能在主庫,讀請求在主從庫都可以完成。

讀操作:主庫、從庫

寫操作:主庫 --> 主庫寫完後同步從庫

寫請求為什麼只能在主庫上,若從庫和主庫上都可以進行讀寫會發生什麼?

主從庫之間是如何同步的

全量同步:當從庫是第一次建立連接並開始同步,該種情況下的同步如下圖:

從庫和主庫建立起連接,並告訴主庫即將進行同步,主庫確認回復後,主從庫間就可以開始同步了。首先,從庫給主庫發送 psync 命令,表示要進行數據同步,主庫根據這個命令的參數來啟動複製。psync 命令包含了主庫的 runID 和複製進度 offset 兩個參數。
(1)runID,是每個 Redis 實例啟動時都會自動生成的一個隨機 ID,用來唯一標記這個實例。當從庫和主庫第一次複製時,因為不知道主庫的 runID,所以將 runID 設為「?」。
(2)offset,此時設為 -1,表示第一次複製。

FULLRESYNC 響應表示第一次複製採用的全量複製,也就是說,主庫會把當前所有的數據都複製給從庫。在第二階段,主庫將所有數據同步給從庫。從庫收到數據後,在本地完成數據加載。這個過程依賴於內存快照生成的 RDB 文件。為了保證主從庫的數據一致性,主庫會在內存中用專門的 replication buffer,記錄 RDB 文件生成後收到的所有寫操作。

主庫會把第二階段執行過程中新收到的寫命令,再發送給從庫。具體的操作是,當主庫完成 RDB 文件發送後,就會把此時 replication buffer 中的修改操作發給從庫,從庫再重新執行這些操作。這樣一來,主從庫就實現同步了。

增量同步:

Redis增量複製是指replica初始化後開始正常工作時主伺服器發生的寫操作同步到從伺服器的過程。增量複製的過程主要是主伺服器每執行一個寫命令就會向從伺服器發送相同的寫命令,從伺服器接收並執行收到的寫命令。

Redis的主節點創建和維護一個環形緩衝複製隊列(即repl_backlog_buffer),從節點部分複製(增量複製)的數據均來自於repl_backlog_buffer。主節點只有一個repl_backlog_buffer,所有從節點共享。

主-從-從模式減少主庫全量同步時的壓力

主從庫模式中,所有的從庫都是和主庫連接,所有的全量複製也都是和主庫進行的。現在,我們可以通過「主 - 從 - 從」模式將主庫生成 RDB 和傳輸 RDB 的壓力,以級聯的方式分散到從庫上。如下圖:

主從庫網絡中斷怎麼辦

Redis的主節點創建和維護一個環形緩衝複製隊列(即repl_backlog_buffer),從節點部分複製(增量複製)的數據均來自於repl_backlog_buffer。主節點只有一個repl_backlog_buffer,所有從節點共享。

當主從庫斷連後,主庫每次都會把收到的寫操作命令,寫入 replication buffer,同時也會把這些操作命令也寫入 repl_backlog_buffer 這個緩衝區。主庫會記錄自己寫到的位置,從庫則會記錄自己已經讀到的位置。主庫來的偏移量是master_repl_offset,對從庫來說從庫已複製的偏移量是slave_repl_offset,正常情況下,這兩個偏移量基本相等。

主從庫的連接恢復之後,從庫首先會給主庫發送 psync 命令,並把自己當前的 slave_repl_offset 發給主庫,主庫會判斷自己的 master_repl_offset 和 slave_repl_offset 之間的差距。在網絡斷連階段,主庫可能會收到新的寫操作命令,所以,一般來說,master_repl_offset 會大於 slave_repl_offset。此時,主庫只用把 master_repl_offset 和 slave_repl_offset 之間的命令操作同步給從庫就行。

哨兵

哨兵其實就是一個運行在特殊模式下的 Redis 進程,主從庫實例運行的同時,它也在運行。哨兵主要負責的就是三個任務:監控、選主(選擇主庫)和通知,哨兵節點其實就是一個特殊的Redis實例節點。

監控:判斷主從庫下線

選主:選出新主庫

通知:讓從庫與主庫同步,通知客戶端與主庫連接

哨兵與沒一個主庫和從庫相連接,並且哨兵節點之間行成集群。

監控

哨兵與沒一個Redis節點相連接並通過PING命令檢測它自己和主、從庫的網絡連接情況,用來判斷實例的狀態。沒一個Redis節點的狀態可以分為」主觀下線「和」客觀下線「。

如果檢測的是從庫,那麼,哨兵簡單地把它標記為「主觀下線」就行了,因為從庫的下線影響一般不太大,集群的對外服務不會間斷。

如果檢測的是主庫,那麼,哨兵還不能簡單地把它標記為「主觀下線」,開啟主從切換。因為很有可能存在這麼一個情況:那就是哨兵誤判了,其實主庫並沒有故障。可是,一旦啟動了主從切換,後續的選主和通知操作都會帶來額外的計算和通信開銷。

在判斷主庫是否下線時,不能由一個哨兵說了算,只有大多數的哨兵實例,都判斷主庫已經「主觀下線」了,主庫才會被標記為「客觀下線」,這個叫法也是表明主庫下線成為一個客觀事實了。這個判斷原則就是:少數服從多數。同時,這會進一步觸發哨兵開始主從切換流程。

選主

當主庫掛了以後,哨兵會在從庫中進行選主,選主主要包括以下三個原則。

首先,優先級最高的從庫得分高。

其次,和舊主庫同步程度最接近的從庫得分高。

最後,ID 號小的從庫得分高。

用戶可以通過 slave-priority 配置項,給不同的從庫設置不同優先級。比如,你有兩個從庫,它們的內存大小不一樣,你可以手動給內存大的實例設置一個高優先級。在選主時,哨兵會給優先級高的從庫打高分,如果有一個從庫優先級最高,那麼它就是新主庫了。如果從庫的優先級都一樣,那麼哨兵開始進行第二個原則判斷。

這個規則的依據是,如果選擇和舊主庫同步最接近的那個從庫作為主庫,那麼,這個新主庫上就有最新的數據。主從庫同步時有個命令傳播的過程。在這個過程中,主庫會用 master_repl_offset 記錄當前的最新寫操作在 repl_backlog_buffer 中的位置,而從庫會用 slave_repl_offset 這個值記錄當前的複製進度。

每個實例都會有一個 ID,這個 ID 就類似於這裡的從庫的編號。目前,Redis 在選主庫時,有一個默認的規定:在優先級和複製進度都相同的情況下,ID 號最小的從庫得分最高,會被選為新主庫。

分片集群

當數據容量越來越大時,如Redis集群的數據量有5G增長到了25G,那麼需要考慮集群的擴容問題,在擴容時一般有兩種方案:

縱向擴展:升級單個 Redis 實例的資源配置,包括增加內存容量、增加磁碟容量、使用更高配置的 CPU。將磁碟容量擴展到50G
簡單直接,但是增加了硬體和成本的限制、當使用 RDB 對數據進行持久化時,如果數據量增加,需要的內存也會增加,主線程 fork 子進程時就可能會阻塞

橫向擴展:橫向增加當前 Redis 實例的個數,就像下圖中,原來使用 1 個 *GB 內存、10GB 磁碟的實例,現在使用三個相同配置的實例。

分片和實例的對應分布關係

在分片集群中,數據需要分布在不同實例上,那麼,數據和實例之間如何對應呢?這就和接下來我要講的 Redis Cluster 方案有關了。不過,我們要先弄明白切片集群和 Redis Cluster 的聯繫與區別。

Redis Cluster 方案採用哈希槽(Hash Slot,接下來我會直接稱之為 Slot),來處理數據和實例之間的映射關係。在 Redis Cluster 方案中,一個切片集群共有 16384 個哈希槽,這些哈希槽類似於數據分區,每個鍵值對都會根據它的 key,被映射到一個哈希槽中。

以只有五個槽為例,展示,數據、哈希槽、實例這三者的映射分布情況,如下圖:

客戶端如何定位數據

客戶端和集群實例建立連接後,實例就會把哈希槽的分配信息發給客戶端。但是,在集群剛剛創建的時候,每個實例只知道自己被分配了哪些哈希槽,是不知道其他實例擁有的哈希槽信息的。那麼,客戶端為什麼可以在訪問任何一個實例時,都能獲得所有的哈希槽信息呢?這是因為,Redis 實例會把自己的哈希槽信息發給和它相連接的其它實例,來完成哈希槽分配信息的擴散。當實例之間相互連接後,每個實例就有所有哈希槽的映射關係了。客戶端收到哈希槽信息後,會把哈希槽信息緩存在本地。當客戶端請求鍵值對時,會先計算鍵所對應的哈希槽,然後就可以給相應的實例發送請求了。

實例和哈希槽的對應關係並不是一成不變的,最常見的變化有兩個:

Redis Cluster 方案提供了一種重定向機制,所謂的「重定向」,就是指,客戶端給一個實例發送數據讀寫操作時,這個實例上並沒有相應的數據,客戶端要再給一個新實例發送操作命令。

需要注意的是,在上圖中,當客戶端給實例 2 發送命令時,Slot 2 中的數據已經全部遷移到了實例 3。在實際應用時,如果 Slot 2 中的數據比較多,就可能會出現一種情況:客戶端向實例 2 發送請求,但此時,Slot 2 中的數據只有一部分遷移到了實例 3,還有部分數據沒有遷移。在這種遷移部分完成的情況下,客戶端就會收到一條 ASK 報錯信息。

這個結果中的 ASK 命令就表示,客戶端請求的鍵值對所在的哈希槽 13320,在實例3上,但是這個哈希槽正在遷移。此時,客戶端需要先給 實例3這個實例發送一個 ASKING 命令。這個命令的意思是,讓這個實例允許執行客戶端接下來發送的命令。然後,客戶端再向這個實例發送 GET 命令,以讀取數據。

在下圖中,Slot 2 正在從實例 2 往實例 3 遷移,key1 和 key2 已經遷移過去,key3 和 key4 還在實例 2。客戶端向實例 2 請求 key2 後,就會收到實例 2 返回的 ASK 命令。ASK 命令表示兩層含義:第一,表明 Slot 數據還在遷移中;第二,ASK 命令把客戶端所請求數據的最新實例地址返回給客戶端,此時,客戶端需要給實例 3 發送 ASKING 命令,然後再發送操作命令。ASK 命令並不會更新客戶端緩存的哈希槽分配信息。


作者:買個橘子
連結:https://juejin.im/post/6894048481422344199

相關焦點

  • 主從哨兵集群終於給你說明白了
    Redis有三種集群模式,第一個就是主從模式,第二種「哨兵」模式,第三種是 Cluster 集群模式。今天就和大家細細聊聊這三種模式。主從複製當其中一臺伺服器更新之後,伺服器會自動的將這臺更新的數據同步到另外一臺伺服器上。通過持久化的功能,redis可以保證就算是服務宕機重啟了,也只有少量的數據會丟失。
  • Redis5.0:簡單的集群模式——主從模式詳解
    主從模式主從模式是最簡單的集群模式,其實就是複製基本只能解決讀寫分離問題, 主機伺服器一旦宕機基本完蛋,不具備高可用。基本上redis的性能瓶頸主要在於網絡IO和內存主頻上面,單機版Redis在不考慮高可用的情況下基本滿足80%的項目需要,因為單機版Redis可以實現10W/S的請求,除非緩存K-V值過大,通過讀寫分離緩存網卡的壓力,否則這個並發處理能力可以應對大部分項目。
  • 認識Redis集群——Redis Cluster
    Redis Cluster與其它集群模式的區別相比較sentinel模式,多個master節點保證主要業務(比如master節點主要負責寫)穩定性,不需要搭建多個sentinel實例監控一個master節點;相比較一主多從的模式,不需要手動切換,具有自我故障檢測,故障轉移的特點;相比較其他兩個模式而言
  • 面試官:Redis有哪幾種集群方案?原理和優缺點是什麼?
    其他哨兵通過該信息可以判斷master的版本,如果該版本高於直接記錄的版本,將會更新當實現了自動發現slave和其他哨兵節點後,哨兵就可以通過定期發送PING命令定時監控這些資料庫和節點有沒有停止服務。
  • Redis的集群搭建,原來這麼簡單
    同時因為槽位的信息是緩存到客戶端,當集群進行了水平擴展時,客戶端和服務端的槽位信息會出現不一致的情況,所以cluster集群提供了糾正機制來實現槽位信息的校驗調整。槽位定位算法cluster默認會對key值使用crc16算法進行hash得到一個整數值,然後用這個整數值對16384進行取模來得到具體槽位。
  • 三歪推薦:Redis常見的面試題
    跳躍表skiplist:跳躍表是有序集合的底層實現之一,redis中在實現有序集合鍵和集群節點的內部結構中都是用到了跳躍表。1秒鐘的數據,而no模式的效率和everysec相仿,但是會丟失上次同步AOF文件之後的所有寫命令數據。
  • 5分鐘完全掌握 Redis
    跳躍表skiplist:跳躍表是有序集合的底層實現之一,redis中在實現有序集合鍵和集群節點的內部結構中都是用到了跳躍表。1秒鐘的數據,而no模式的效率和everysec相仿,但是會丟失上次同步AOF文件之後的所有寫命令數據。
  • Redis Sentinel-深入淺出原理和實戰
    因為哨兵執行故障轉移需要「大部分」的哨兵都同意才行,如果只有兩個哨兵實例,正常運作還好,就像這樣。❞前面提到的大部分哨兵同意涉及到兩個參數,一個叫quorum,如果Sentinel集群有quorum個哨兵認為master宕機了,就「客觀」的認為master宕機了。另一個叫majority...❝等等等等,不是已經有了一個叫什麼quorum的嗎?為什麼還需要這個majority?
  • Docker 搭建 Redis Cluster 集群環境
    關於 Redis Cluster 集群更多的內容請閱讀《最通俗易懂的 Redis 架構模式詳解》。開啟保護模式以後,需配置 bind ip 或者設置訪問密碼;關閉保護模式,外部網絡可以直接訪問;daemonize:是否以守護線程的方式啟動(後臺啟動),默認 no;appendonly:是否開啟 AOF 持久化模式,默認 no;cluster-enabled:是否開啟集群模式,默認 no;cluster-config-file:集群節點信息文件;cluster-node-timeout:集群節點連接超時時間
  • 去pdd面試,redis把我面哭了【附面試答案】
    2、看你在項目中用了redis,我們先聊聊redis吧,常用的數據結構有哪幾種,在你的項目中用過哪幾種,以及在業務中使用的場景,redis的hash怎麼實現的,rehash過程講一下和JavaHashMap的rehash有什麼區別?redis cluster有沒有了解過,怎麼做到高可用的?3redis集群和哨兵機制有什麼區別?redis的持久化機制了解嗎?
  • Redis 單例、主從模式、sentinel 以及集群的配置方式及優缺點對比
    redis主從模式解決了數據備份和單例可能存在的性能問題,但是其也引入了新的問題。由於主從模式配置了三個redis實例,並且每個實例都使用不同的ip(如果在不同的機器上)和埠號。根據前面所述,主從模式下可以將讀寫操作分配給不同的實例進行從而達到提高系統吞吐量的目的,但也正是因為這種方式造成了使用上的不便,因為每個客戶端連接redis實例的時候都是指定了ip和埠號的,如果所連接的redis實例因為故障下線了,而主從模式也沒有提供一定的手段通知客戶端另外可連接的客戶端地址,因而需要手動更改客戶端配置重新連接。
  • 一不小心肝出了4W字的Redis面試教程
    集群集群概述Redis作為緩存的高效中間件,在我們日常的開發中被頻繁的使用,今天就來說一說Redis的四種模式,分別是單機版、主從複製、哨兵、以及集群模式。但是,我們作為有抱負的程式設計師,僅限於單機版和主從模式的crud是不行的,至少也要了解哨兵和集群模式的原理,這樣面試的時候才能和面試官扯皮啊。
  • Hunt Redis 1.0.0 發布,D 語言 Redis 客戶端
    > String類型的命令處理 Hashes類型的命令處理 Lists類型的命令處理 Sets類型的命令處理 Sorted Sets類型的命令處理 事務 批量命令處理 訂閱/發布 持久化的控制命令 遠程控制命令 分片
  • acl 框架中的 Redis 庫已經支持集群版 Redis 3.0
    redis 進行分庫了,之前人們為了使單機版的 redis 能支持集群方式,往往是在客戶端或通過加一個中間的代理層(比如使用 tweaproxy)做很多工作,現在有了集群版的 redis3.0 ,這些額外的操作都不再需要。
  • redis學習筆記(四)主從數據同步
    在redis恢復數據時我們可以依賴於aof日誌或rdb日誌,但是redis在運行中該如何保證服務的可靠性,就需要依賴redis主從和哨兵集群
  • 開源 | Overlord:嗶哩嗶哩基於 Go 語言編寫的 memcache 和 redis&cluster 代理及集群管理組件
    點擊連結或圖片即可閱讀喜歡請分享到朋友圈哦Overlord 是嗶哩嗶哩基於 Go 語言編寫的 memcache 和
  • Redis哨兵(Sentinel)模式如何做到高可用的?
    ——柏拉圖引導語Sentinel(哨兵)是Redis的高可用性解決方案:由一個或多個Sentinel實例組成的Sentinel系統可以監視任意多個主伺服器,以及這些主伺服器屬下的所有從伺服器,並在被監視的主伺服器進入下線狀態時,自動將下線主伺服器屬下的某個從伺服器升級為新的主伺服器,然後由新的主伺服器代替已下線的主伺服器繼續處理命令請求。
  • 46道Redis面試題,含參考答案!
    所以 redis 具有快速和數據持久化的特徵,如果不將數據放在內存中,磁碟 I/O 速度為嚴重影響 redis 的性能。在內存越來越便宜的今天,redis 將會越來越受歡迎, 如果設置了最大使用的內存,則數據已有記錄數達到內存限值後不能繼續插入新值。9、Redis 集群方案應該怎麼做?都有哪些方案?
  • 如何實現redis主從複製?
    主從複製,主要優勢在於實現了數據備份(主機和從機數據同步一致)、讀寫分離(主機主要負責寫入數據,從機讀數據,在讀大於寫的項目中提高了性能)。最後也為後續集成哨兵機制和集群的實現提供了依據。從機Slave(讀)6379redis5.0第一步:安裝redis三臺伺服器上分別安裝redis,三臺伺服器redis配置為方便可配置一致第二步:添加主從配置項主機(192.168.1.6) 不做任何修改,兩臺從機配置文件分配添加一下內容# replicaof <masterip> <masterport>
  • NoSQL DB 系列解讀:Redis-KV 七個關鍵知識點
    關於這個問題我們首先要明白 Redis 分布式集群的整體框架圖,如圖 5.1 所示:圖中所示是一個數據分片的分布式架構,包括客戶端、代理層、集群分組、監控控制層。客戶端通過訪問代理層提供的虛擬地址來訪問 Redis 資料庫資源,數據請求經過代理層之後可以通過哈希或者其他算法映射到具體集群分組的 Master 節點,然後完成數據請求。