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
    • 6381下線重啓仍追隨6379,同時開啓aof,命令如下:
      redis-server ~/testRedis/6381.conf --replicaof 127.0.0.1 6379 --appendonly yes

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-server ./26380.conf --sentinel
    • redis-server ./26381.conf --sentinel

    上圖,哨兵配置文件只配置了redis集羣的主機ip和端口,但是哨兵啓動後卻獲取了整個redis集羣所有實例的信息,是因爲redis集羣中從機追隨主機時主機已經知道從機的信息了,所以哨兵通過獲取主機信息既能獲取從機的信息
    另外,哨兵又是如何獲取其他哨兵的信息的呢?這是因爲其使用了redis本身的發佈訂閱功能;即在redis集羣的master上發佈各哨兵信息,哨兵們自行訂閱,可以通過在redis任意實例上執行PSUBSCRIBE * 來觀察哨兵之間的交互信息,如圖:

  • 4、當redis集羣的master下線後哨兵集羣是會自動修改自身的配置文件,將sentinel monitor mymaster後面換成最新的master的ip加端口,並且還會在配置文件後追加識別到的redis的其他從機和其他哨兵信息,如圖

    至此,redis的主從複製集羣介紹完畢,如有紕漏還望指正!後續會繼續更新redis的分片集羣......
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章