redis叢集之主從複製叢集的原理和部署

木木他爹 發表於 2022-11-29
Redis

最近在覆盤redis的知識,所以本文開始希望介紹下redis的叢集架構、原理以及部署;本文主要介紹redis的主從複製叢集,包括其架構模型,原理,高可用等;

一、主從叢集的介紹

  redis的主從複製叢集為了提高效率降低客戶端等待時長,主從間的資料同步採用的是弱一致性的策略,即客戶端請求發到主機後,不論是否同步到備機,都認為此次請求是成功的,這樣雖然效率上提高了,但是資料一致性卻得不到保障;所以redis提供了一個min-replicas-to-write引數用來配置,至少有幾臺從機與主機保持連線時主機才能執行寫入操作,一定程度上維護了資料的一致性;
  其次,使用redis主從複製叢集主要是為了解決單點故障問題,從機相當於主機的備份,且只提供讀不提供寫入功能,為的是在主機故障導致不能對外提供服務時從機能快速接替從而實現叢集的高可用;而叢集間主從的切換顯然不能透過人工來完成,所以redis提供了一個哨兵的概念,顧名思義,哨兵即負責監控放哨,當主機不可用時迅速從從機中選出一個主機來,而這又涉及到以下兩個方面;

  • 1、如何判斷redis叢集的master不可用
    判斷master不可用使用的是過半機制,即當哨兵叢集中某一個哨兵發現master不可用時,會向叢集其他哨兵傳送is-master-down-by-addr指令詢問master是否真的掛了,叢集其他哨兵收到指令後會根據自身與master的連線情況判斷是否真的掛了,然後給第一個哨兵作出響應,是否贊成master掛了;當超過叢集數量一半加1的機器認為master掛了那麼就投票透過,即認為redis叢集的master真的掛了,需要進行選主操作;所以哨兵也應該是叢集部署的,單個部署的話與主機是一對一的關係,不穩定性太大容易造成誤判
  • 2、哨兵發現master掛了過後又是如何給redis叢集做主從個切換的呢(哨兵的選主)
    當第一個發現master掛了的哨兵收到其他哨兵的響應確認master掛了後,會繼續傳送一個請求,希望自己成為哨兵的leader來進行redis叢集的主從切換操作,此時該哨兵被稱為候選者;叢集中的所有哨兵都只有一次投票機會,投給自己或者別人,需要注意的是隻有候選者才能將票投給自己;哨兵之間的選主使用的是Raft演算法

注意:
1、一般最先發現master掛了的哨兵會作為哨兵叢集選主的候選者,會自動投給自己一票
2、如果同一時點有兩個哨兵同時發現master掛了,那麼就會有兩個候選者,他們都投給自己一票,需要注意的是叢集中的每個哨兵只有一次投票機會,所以兩個候選者之外的哨兵肯定只會給兩個候選者中的一個投票

二、主從叢集的安裝部署

我在安裝步驟裡做了一些筆記,大概也囊括了主從複製的大部分特性,並且也貼上了關鍵命令執行的圖片,所以我就不拎出來單獨介紹了

1、環境準備

  • 1、先在linux下安裝redis,這裡我就不貼教程了,我安裝的是redis-5.0.5版本
  • 2、進入redis安裝目錄下的utils資料夾,執行 ./install_server.sh命令然後無腦回車,自動安裝redis服務,做叢集的話則第一遍預設執行6379,第二遍第三遍可以把埠號換成6380和81,這樣我們主機裡就有三個redis服務了
  • 3、安裝完後執行service redis_6379 stop、service redis_6380 stop和service redis_6381 stop分別停掉這三臺主機,因為後續演示我們需要前臺阻塞執行檢視日誌
  • 4、在任意目錄下建立一個資料夾testRedis,然後把/etc下的redis的配置檔案複製過來,因為我們叢集測試會給一堆配置,所以另外複製一份,不動系統本身的配置,命令如下
    • mkdir testRedis
    • cd testRedis
    • cp /etc/redis/* ./
  • 5、編輯/testRedis下的三個配置檔案,將
    • daemonize置為no,使redis服務前臺執行,方便觀察日誌;
    • 註釋掉 logfile /var/log/redis_6379.log使其前臺列印
    • appendonly置為no,關閉aof使其只使用rdb,具體原因後面會分析

    上面的配置完成後,表示接下來啟動的redis例項是會前臺阻塞執行且不使用aof的持久化方式

  • 6、啟動三個redis例項
    • redis-server ~/testRedis/6379.conf
    • redis-server ~/testRedis/6380.conf
    • redis-server ~/testRedis/6381.conf
  • 7、啟動三個reids-cli連線三個例項
    • redis-cli -p 6379
    • redis-cli -p 6380
    • redis-cli -p 6381
  • 8、透過命令的方式使6380和6381作為slave追隨6379
    • 老版本命令 slaveof 127.0.0.1 6379
    • 新版本(5.0)命令 replicaof 127.0.0.1 6379

    注意:
    1、主從叢集搭建完畢後,在6379set資料後80和81就能同步過去了,但是預設情況下80、81是不能寫入的,會報 READONLY You can't write against a read only slave的錯誤;並且從機第一次追隨主機時是會flush掉本身所有資料的,會全量同步主機的資料過來;

  • 9、模擬從機下線
    • 6381下線重啟仍追隨6379,不開啟aof,命令如下:
      redis-server ~/testRedis/6381.conf --replicaof 127.0.0.1 6379
      redis叢集之主從複製叢集的原理和部署
    • 6381下線重啟仍追隨6379,同時開啟aof,命令如下:
      redis-server ~/testRedis/6381.conf --replicaof 127.0.0.1 6379 --appendonly yes
      redis叢集之主從複製叢集的原理和部署

1、由上面兩個圖可以看到,開啟aof時從機(6381)是會先flush掉自身資料重新從master(6379)身上全量同步資料的,所以從效率上來說增量同步肯定優於全量同步的
2、從機下線重啟後仍然追隨原主機(即下線前做過主從同步)的話,如果從機重啟時未開啟aof,那麼會做增量同步,否則則會進行全量同步;因為rdb中會記錄原主機資訊而aof不會;

  • 10、模擬主機下線
    直接終止6379的程式,那麼此時6380和81會報Error condition on socket for SYNC: Connection refused錯誤,並且均只能提供讀服務不能提供寫入能力,所以此時可以人為的讓6380或6381使自己作為master,命令如下
    • replicaof no one
      然後再使另一個例項追隨新的matster,這樣redis叢集又可以對外提供服務了,但是這種靠人為選主並切換終究不靠譜,所以就要用到哨兵模式,用來監控,當master掛了的時候能快速的響應,重新選主,使叢集快速可用
  • 11、叢集相關的配置
    • replica-serve-stale-data yes 從機同步主機資料期間是否將自己原本的舊資料對外暴露,預設對外暴露
    • replica-read-only yes 從機是否開啟只讀模式,預設從機只讀
    • repl-diskless-sync no 主機以何種方式將rdb檔案同步給備機,yes表示主機生成rdb後直接透過網路IO將資料發給備機;no的話表示主機先將rdb透過磁碟IO落本機磁碟再透過網路傳送給備機;預設為先落磁碟再傳送給從機
    • repl-backlog-size 1mb
      增量複製的大小;即當從機同步完後主機會維護一個增量資料的佇列,從機下次備份時可以拿著offset從佇列裡直接取增量資料;預設是1m,但是需要根據業務的寫入量來確定該值大小;因為如果業務寫入過多,從機下線恢復這段時間寫入超過預設的1m的話,那麼只使用增量同步的話就會丟失資料了
    • min-replicas-to-write 3
      可以理解成master能否執行寫入操作的一個限制條件;當有指定個數的從機與主機保持連線時master才能執行寫操作;預設為當有3個從機與master保持連線master才能執行寫入操作,否則master不對外提供寫入能力;這樣雖然不能保證所有的從機都能同步到master的資料,但是可以保證至少有幾個從機存活master才能執行寫入操作,避免丟失過多資料;值為0表示關閉該限制
    • min-replicas-max-lag 10
      從機是否與主機保持連線的標準;預設為延遲小於10s的從機才被認為是健康的,是與主機保持連線的

三、哨兵叢集搭建

  • 1、由於哨兵我們也搭建一個叢集,所以建立三個哨兵的配置檔案,在testRedis下執行以下命令
    • vi 26379.conf,按i輸入:
    • port 26379
    • sentinel monitor mymaster 127.0.0.1 6379 2

    一個redis哨兵叢集可以監控多個redis叢集,所以mymaster表示redis叢集的名稱,後面跟redis叢集master的ip和埠;最後一個數字2表示redis叢集中幾個例項透過後投票有效,即我們常說的過半加1後的那個值,因為我的redis叢集只有三臺機器,所以這個值為3/2+1=2

    • cp 26379.conf 26380.conf 複製26379的配置,修改26380.conf裡的port為26380
    • cp 26379.conf 26381.conf 複製26379的配置,修改26381.conf裡的port為26381
  • 2、啟動redis叢集中的各個例項,以6379為主6380和6381為slave追隨6379
  • 3、啟動哨兵叢集
    • redis-server ./26379.conf --sentinel
      redis叢集之主從複製叢集的原理和部署
    • redis-server ./26380.conf --sentinel
      redis叢集之主從複製叢集的原理和部署
    • redis-server ./26381.conf --sentinel
      redis叢集之主從複製叢集的原理和部署

    上圖,哨兵配置檔案只配置了redis叢集的主機ip和埠,但是哨兵啟動後卻獲取了整個redis叢集所有例項的資訊,是因為redis叢集中從機追隨主機時主機已經知道從機的資訊了,所以哨兵透過獲取主機資訊既能獲取從機的資訊
    另外,哨兵又是如何獲取其他哨兵的資訊的呢?這是因為其使用了redis本身的釋出訂閱功能;即在redis叢集的master上釋出各哨兵資訊,哨兵們自行訂閱,可以透過在redis任意例項上執行PSUBSCRIBE * 來觀察哨兵之間的互動資訊,如圖:redis叢集之主從複製叢集的原理和部署

  • 4、當redis叢集的master下線後哨兵叢集是會自動修改自身的配置檔案,將sentinel monitor mymaster後面換成最新的master的ip加埠,並且還會在配置檔案後追加識別到的redis的其他從機和其他哨兵資訊,如圖
    redis叢集之主從複製叢集的原理和部署
    至此,redis的主從複製叢集介紹完畢,如有紕漏還望指正!後續會繼續更新redis的分片叢集......