主從哨兵集群終於給你說明白了

2021-01-11 moon聊技術

前言碎語

說起 Redis 應該沒有人會陌生了吧,作為開發中最最最最最最最常用的 nosql,它的重要性不言而喻。

Redis有三種集群模式,第一個就是主從模式,第二種「哨兵」模式,第三種是 Cluster 集群模式。

今天就和大家細細聊聊這三種模式。

主從複製

當其中一臺伺服器更新之後,伺服器會自動的將這臺更新的數據同步到另外一臺伺服器上。

通過持久化的功能,redis可以保證就算是服務宕機重啟了,也只有少量的數據會丟失。但是在真實的使用場景當中,如果真的只有一臺伺服器,並且恰好宕機了,那麼就會導致整個服務都不可用,因此redis提供了集群的方式來部署,可以避免這種問題。

在主從複製這種集群部署模式中,我們會將資料庫分為兩類,第一種稱為主資料庫(master),另一種稱為從資料庫(slave)。

主資料庫會負責我們整個系統中的讀寫操作,從資料庫會負責我們整個資料庫中的讀操作。

其中在職場開發中的真實情況是,我們會讓主資料庫只負責寫操作,讓從資料庫只負責讀操作,就是為了讀寫分離,減輕伺服器的壓力。

但是我在實際開發中會遇到一種情況,該數據是個熱點數據,我們知道,數據同步一定是會耗時的,那麼當一個熱點數據進入master中,而slave沒有來得及更新,再去讀這個數據就會造成數據不一致現象,所以當時我的方案就是直接去讀master節點,這個邏輯同樣適用於mysql主從中出現的問題。

主從同步原理

當一個從資料庫啟動時,它會向主資料庫發送一個SYNC命令master收到後,在後臺保存快照,也就是我們說的RDB持久化,當然保存快照是需要消耗時間的,並且redis是單線程的(redis後面也支持了多線程,這裡我們先不講),在保存快照期間redis收到的命令會緩存起來,快照完成後會將緩存的命令以及快照一起打包發給slave節點,從而保證主從資料庫的一致性。從資料庫接受到快照以及緩存的命令後會將這部分數據寫入到硬碟上的臨時文件當中,寫入完成後會用這份文件去替換掉RDB快照文件,當然,這個操作是不會阻塞的,可以繼續接收命令執行,具體原因其實就是fork了一個子進程,用子進程去完成了這些功能。因為不會阻塞,所以,這部分初始化完成後,當主資料庫執行了改變數據的命令後,會異步的給slave,這也就是我們說的複製同步階段,這個階段會貫穿在整個主從同步的過程中,直到主從同步結束後,複製同步才會終止。

那麼我上文提到的數據不一致的現象又是怎麼回事呢?

是因為redis採用了樂觀複製的策略:

容忍一定時間內主從資料庫的數據是不一致的,但是會保證最終的結果一致。

所以當主從複製發生時,正常情況下的命令都會在主資料庫完成,然後直接反回給客戶端,這樣我們的性能就不會受到影響了,因為這裡是主資料庫先完成命令,那麼就會產生其他問題。

舉個例子,假如現在有1個master,6個slave,現在只有兩個slave完成了同步,master寫了新命令,在master準備將此命令傳輸給其他slave時,此刻其他的slave斷電了,那麼就會造成數據不一致的現象發生。

所以redis針對這種情況作了兩個配置

min-slaves-to-write 2 (只有2個及以上的從資料庫連接到了主資料庫時,master庫才是可寫的)

min-slaves-max-lag 10 (10秒slave沒有和master進行交互就認為丟失連結)

無硬碟複製

我們剛剛說了主從之間是通過RDB快照來交互的,雖然看來邏輯很簡單,但是還是會存在一些問題:

1.master禁用了RDB快照時,發生了主從同步(複製初始化)操作,也會生成RDB快照,但是之後如果master發成了重啟,就會用RDB快照去恢復數據,這份數據可能已經很久了,中間就會丟失數據2.在這種一主多從的結構中,master每次和slave同步數據都要進行一次快照,從而在硬碟中生成RDB文件,會影響性能為了解決這種問題,redis在後續的更新中也加入了無硬碟複製功能,也就是說直接通過網絡發送給slave,避免了和硬碟交互,但是也是有io消耗的。

增量複製

為什麼會有增量複製?

剛剛我們說了複製的原理,但是他的缺點是很明顯的,就是在斷開主從連結後,即使你只發生了一條數據變化,也需要將所有的數據通過SYNC命令用RDB將所有的數據同步給slave,但是其實並不需要同步所有的數據,只需要將改變的這小部分數據同步給slave就好了

所以為了解決這個問題,redis就有了增量複製。

這個原理其實是很簡單的,學過kafka 的小夥伴應該知道,kafka消費是通過偏移量來計算的,redis的增量複製也是如此。

master會記下每個slave的id,在複製期間,如果有新消息,會將新消息(其實是新的命令,當然只包括讓數據放生變動的命令,如 set 這種 )存放在一個固定大小的循環隊列中,這個大小是可以配置的,當然這時候發送的就是PSYNC命令了,然後master會在複製完成後將這部分數據發送給slave,這樣就在很大程度上保證了數據一致性。

哨兵模式

上文咱們說主從複製,在這種一主多從的結構中,我們讓主從資料庫做到了讀寫分離,也讓從資料庫能夠完成數據備份的功能,可是也留下了一個比較嚴重的問題,當master掛了之後,只能由運維人員重新選擇一個slave升級成master,然後繼續提供服務。

想想一下,你國慶正放假,躺在三亞的海邊沐浴著陽光,享受著香檳,突然你們boss給你來了個電話,說線上的master掛了,是不是會心裡一句mmp(嗯,我這是文明用語)???,所以,redis為了你考慮,在redis2.6版本中,他來了他來了---哨兵模式

什麼是哨兵?

顧名思義,哨兵其實就是放哨的,它主要會有完成兩個功能。

1.監控整個主資料庫和從資料庫,觀察它們是否正常運行2.當主資料庫發生異常時,自動的將從資料庫升級為主資料庫,繼續保證整個服務的穩定哨兵其實是一個獨立的進程,如下圖

當然,上圖只是一個哨兵存在時的情況,但在現實中還會有兩個,甚至更多哨兵存在的情況

實現原理

當一個哨兵進程啟動時,它會先通過配置文件,找我們的主資料庫,當然,我們這裡也只需要配置其監控的主資料庫就好,之後哨兵會自動發現所有複製該主資料庫的從資料庫,當然一個哨兵是可以監控多個redis系統的,同時,多個哨兵也可以同時監控一個redis系統的,這裡moon先給大家灌輸下這個概念,大家理解下,詳細的我會在後文提到。

哨兵進程啟動後後會和master建立兩條連結

1.用來獲取其他同樣在監控著此redis系統的哨兵信息2.發送一個info命令來獲取此redis系統master本身的信息當和master完成連結建立後,該哨兵就會定時的做以下三件事情

1.每10秒會向master和slave發送info命令2.每2秒會向master和slave發送自己的信息3.每1秒會向master,slave以及其他同樣在監控著此redis系統的哨兵發送ping命令以上三個操作可是說是哨兵的核心了,下面就著重介紹一下這三個命令

首先,info命令可以讓哨兵獲取到當前資料庫的信息,比如運行id,複製信息等等,從而實現新節點的自動發現,從資料庫的信息正是從info命令中獲取的,獲取從資料庫信息後,就會和從資料庫建立兩條連結,和主資料庫建立的連結是完全一樣的,之後就會每10s向主從資料庫發送info命令,當有新的從資料庫加入時,就會從info命令中發現了,從而將這個新的slave加入自己的監控列表中。

當然如果有新的哨兵加入到了監控中,其他哨兵也是從這個info命令中獲取的。

於此,就完成了對資料庫以及其他哨兵的自動發現和監控,是不是很easy呢??

以上講了自動發現資料庫和其他的哨兵節點,之後哨兵就開始了它的工作,就是去監控這些資料庫和節點有沒有停止,哨兵就會每隔一段時間向這些節點發送PING命令,如果一段時間沒有收到回復後,那麼這個哨兵就會認為該節點已經掛了,我們將其稱為主觀下線。

如果該節點是master,哨兵就會向其他節點詢問,看其他節點時候也認為該master掛了,我們可以認為他們在投票,當票數達到了一定的次數,那麼哨兵就認為該節點真的掛了,我們成為客觀下線,然後哨兵之間就會選舉,選出一個領頭的哨兵對主從資料庫發起故障的修復。

哨兵選舉過程

1.第一個發現該master掛了的哨兵,向每個哨兵發送命令,讓對方選舉自己成為領頭哨兵2.其他哨兵如果沒有選舉過他人,就會將這一票投給第一個發現該master掛了的哨兵3.第一個發現該master掛了的哨兵如果發現由超過一半哨兵投給自己,並且其數量也超過了設定的quoram參數,那麼該哨兵就成了領頭哨兵4.如果多個哨兵同時參與這個選舉,那麼就會重複該過程,知道選出一個領頭哨兵選出領頭哨兵後,就開始了故障修復,會從選出一個從資料庫作為新的master

master選舉過程

1.從所有在線的從資料庫中,選擇優先級最高的從資料庫2.如果有多個優先級高的從資料庫,那麼就會判斷其偏移量,選擇偏移量最小的從資料庫,這裡的偏移量就是增量複製的3.如果還是有相同條件的從資料庫,就會選擇運行id較小的從資料庫升級為mastercluster集群模式

在redis3.0版本中支持了cluster集群部署的方式,這種集群部署的方式能自動將數據進行分片,每個master上放一部分數據,提供了內置的高可用服務,即使某個master掛了,服務還可以正常地提供,我們先來看張圖:

使用cluster集群模式,只需要將每個資料庫節點的cluster-enabled配置選項打開即可,但是每個cluster集群至少要保證有3個主資料庫才能正常運行。

cluster集群模式是怎麼存放數據的?

一個cluster集群中總共有16384個節點,集群會將這16384個節點平均分配給每個節點,當然,我這裡的節點指的是每個主節點,就如同下圖:

鍵是如何和16384個插槽做關聯的?

redis將每個redis的鍵的鍵名有效部分使用CRC16算法計算出散列值,然後與16384取餘數,這樣的就可以使每個鍵能夠儘量的均勻分布在16384個插槽中。

插槽是如何和節點做關聯的?

1.插槽之前沒有被分配過,現在想分配給指定節點2.插槽之前被分配過,現在想移動指定節點第一種情況可以通過cluster add slot s 命令來實現

第二種情況的原理相對麻煩一點,但是redis也提供的便捷的方式去操作,我們可以使用redis-trib.rb去實現

如何獲取與插槽對應的節點?

當客戶端向redis集群中的任意一個節點發送命令後,該節點都會判斷當前鍵的信息是否存在於當前節點:

如果存在,那麼就會像單機的reids一樣執行命令。如果不存在,就會返回一個move重定向請求,告訴客戶端負責該數據的節點是哪一個,然後客戶端會向該節點發送命令再次請求獲取數據新節點的加入

需要通過cluster meet命令來實現:

cluster meet ip port

ip port 是我們已運行的redis集群中任意一個節點的地址和埠號,新節點在客戶端輸入命令後,會與命令中的節點進行握手,握手後,命令中的集群節點會將這個新節點的信息分享給集群中的每一個節點。

故障恢復

判斷故障的邏輯其實與哨兵模式有點類似,在集群中,每個節點都會定期的向其他節點發送ping命令,通過有沒有收到回復來判斷其他節點是否已經下線。

如果長時間沒有回覆,那麼發起ping命令的節點就會認為目標節點疑似下線,也可以和哨兵一樣稱作主觀下線,當然也需要集群中一定數量的節點都認為該節點下線才可以,我們來說說具體過程:

1。當A節點發現目標節點疑似下線,就會向集群中的其他節點散播消息,其他節點就會向目標節點發送命令,判斷目標節點是否下線2.如果集群中半數以上的節點都認為目標節點下線,就會對目標節點標記為下線,從而告訴其他節點,讓目標節點在整個集群中都下線如何提高redis的讀寫能力

這個問題也是我們之前拋出來的問題,我們放一張圖大家就會很容易明白了:

提高寫能力只需要橫向擴容master

提高讀能力只需要橫向擴容slave

結語

關於這三種部署的方式,基本上在我知道的公司都毫無疑問直接選擇cluster模式,當然具體的選擇還是要看公司的規模了,畢竟技術服務於業務,選擇合適於當前業務的,就是最好的。

下期見~

相關焦點

  • Redis系列 - 主從庫模式、哨兵和分片集群
    哨兵哨兵其實就是一個運行在特殊模式下的 Redis 進程,主從庫實例運行的同時,它也在運行。哨兵主要負責的就是三個任務:監控、選主(選擇主庫)和通知,哨兵節點其實就是一個特殊的Redis實例節點。監控:判斷主從庫下線選主:選出新主庫通知:讓從庫與主庫同步,通知客戶端與主庫連接
  • Redis5.0:簡單的集群模式——主從模式詳解
    主從模式主從模式是最簡單的集群模式,其實就是複製基本只能解決讀寫分離問題, 主機伺服器一旦宕機基本完蛋,不具備高可用。哨兵模式哨兵模式基本就是主從模式的升級版, 主要解決高可用問題,實現自動容錯和恢復。
  • 面試官:Redis有哪幾種集群方案?原理和優缺點是什麼?
    雖然現在各大雲平臺有提供緩存服務可以直接使用,但了解一下其背後的實現與原理總還是有些必要(比如面試), 本文就一起來學習一下Redis的幾種集群方案。主從複製模式主從複製模式中包含一個主資料庫實例(master)與一個或多個從資料庫實例(slave),如下圖
  • redis學習筆記(四)主從數據同步
    在redis恢復數據時我們可以依賴於aof日誌或rdb日誌,但是redis在運行中該如何保證服務的可靠性,就需要依賴redis主從和哨兵集群
  • Redis 單例、主從模式、sentinel 以及集群的配置方式及優缺點對比
    redis主從模式解決了數據備份和單例可能存在的性能問題,但是其也引入了新的問題。由於主從模式配置了三個redis實例,並且每個實例都使用不同的ip(如果在不同的機器上)和埠號。根據前面所述,主從模式下可以將讀寫操作分配給不同的實例進行從而達到提高系統吞吐量的目的,但也正是因為這種方式造成了使用上的不便,因為每個客戶端連接redis實例的時候都是指定了ip和埠號的,如果所連接的redis實例因為故障下線了,而主從模式也沒有提供一定的手段通知客戶端另外可連接的客戶端地址,因而需要手動更改客戶端配置重新連接。
  • 如何實現redis主從複製?
    主從複製,主要優勢在於實現了數據備份(主機和從機數據同步一致)、讀寫分離(主機主要負責寫入數據,從機讀數據,在讀大於寫的項目中提高了性能)。最後也為後續集成哨兵機制和集群的實現提供了依據。一、多臺伺服器上配置主從複製Redis從5.0以後主從配置屬性發生了變化,在5.0之前配置的是slaveof,5.0以後變成了replicaof伺服器用途redis埠號備註centos7 192.168.1.6主機Master(寫)6379redis5.0centos7 192.168.1.4從機Slave(讀)6379redis5.0centos7 192.168.1.5
  • Redis的集群搭建,原來這麼簡單
    雖然整體來說薪資漲幅不大,但已經基本上達到大廠薪資的90%,還是可以的呀,重點人家是錢多活少還離家近,你說這氣人不氣人。他拿到這樣的offer證明肚子裡還是有點東西的哈。罷了罷了,啥也別想了,淦就完了。回歸正題,上篇主要說了下Redis的主從複製是如何做的,高可用集群有幾種方式部署(傳送門《原來你是這樣的高可用呀》)。
  • 面試系列 - Redis 持久化和主從複製總結(二)
    RDB;用作數據備份:RDB 雖然是很重的操作,但是對數據備份很有作用,文件大小比較小,可以按天或按小時進行數據備份;主從,從開?問題1,maxmemory 不一致:例如 master 節點配置4G,slave 節點配置2G,如果在進行某一次全量複製時,slave 節點加載 master 節點的 RDB 文件數據時發現自身2G內存不夠用,這時就會觸發 slave 節點 maxmemory 策略,將數據進行淘汰,更可怕的是,在高可用的集群環境下
  • 終於不再望「水」興嘆,雲端哨兵喝上深泉水
    西藏軍區攜手地方水利部門解決邊防哨所冬季用水難題雲端哨兵喝上深泉水中國國防報訊 平措仁青、記者晏良報導:立冬時節,一股地下泉水從鑽孔中噴湧而出半年時間,施工方鑿破凍土層,向下挖了220米,終於掘到深泉。砌上保溫磚,安裝過濾網,鋪設抽水管……大家晝夜勞作,終於在封山期到來前抽水上哨。凍中能飲深泉,困擾乃堆拉哨兵半個多世紀的吃水難題至此畫上休止符。深泉湧雲端,只是駐藏部隊科技強邊的一個縮影。近年來,西藏軍區將具有國際領先水平的多種材料用於「雲中哨樓」建設,防漏、制氧、取暖等諸多難題迎刃而解。
  • 終於學會了 MySQL 主從配置和讀寫分離
    面試官:那你說說資料庫是主從怎麼配置?小阿花:額,都是 DBA 幫我們搞好的,我們直接用就好了。面試官:你們主從結構遇到過什麼故障沒,比如從庫或者主庫掛掉了,怎麼解決的?小阿花:這個也是 DBA 搞的。面試官:(微笑)好的,今天就到這裡,回去等通知吧。
  • 淺談Redis主從複製
    Redis在京東的使用也是非常普遍的,包括很多關鍵業務上的使用,由於Redis官方集群還未發布,在使用Redis的過程中需要面對Redis的單點問題,京東採用的是一種比較通用的解決方案即由主從備份再加相應的主從切換(在一些場景下可能進行讀寫分離),使主Redis出現失效的時候可以快速的切換到從Redis上。
  • 《星際爭霸2》機械哨兵有什麼能力 機械哨兵能力講解
    導 讀 星際爭霸2這款遊戲中是有很多的角色供玩家們選擇,機械哨兵在星靈種族中是一個強有力阻擋的兵種,很家尤其是新手玩家可能不知道,那麼在遊戲中機械哨兵有什麼能力
  • 哨兵嚮導文安利!《將我馴養》噓,這裡有一隻野生的哨兵!
    大家好,好久不見,我是小鯨魚,今天要給大家分享的是:哨兵嚮導文安利!《將我馴養》噓,這裡有一隻野生的哨兵!他的精神體是鵝by茶深簡介:孩子都快生好了才來跟我說離婚?範陽洲把一杯水推到他的面前,說:「葉矜,對不起,你真的不是我的理想型。」短評:清純豎琴海豹嚮導VS偽賢惠暴躁家鵝哨兵將我馴養by肚皮三層肉簡介:噓,這裡有一隻野生的哨兵,你可以嘗試馴養他。從背後慢慢地接近,小心不要發出任何聲音。他會伸出爪子撓你,假裝掙扎得很厲害。
  • 終於有人說明白了
    終於有人說明白了。咱們之前討論過這麼一個話題,就是男女之間。有沒有純友誼。當然是有很少!也很難!所以咱們今天就。來說一說,為什麼男女之間很難於。有純友誼!咱們現在。一一下就是男女之間!的純友誼!不同於同性友誼的事!異性!扭於你!有需要做到!哪怕關係再親密,也要。對對方沒有愛情方面的念頭!晚走的多近。也不會發生一些出格的事情。這就是。男女間的純友誼!