能堅持別人不能堅持的,才能擁有別人未曾擁有的。
關注左上角編程大道
公眾號,讓我們一同堅持心中所想,一起成長!!
《【面試突擊】— Redis篇》-- Redis的主從復制?哨兵機制?
在這個系列里,我會整理一些面試題與大家分享,幫助年后和我一樣想要在金三銀四准備跳槽的同學。
我們一起鞏固、突擊面試官常問的一些面試題,加油!!
《【面試突擊】— Redis篇》--Redis數據類型?適用於哪些場景?
《【面試突擊】— Redis篇》--Redis的線程模型了解嗎?為啥單線程效率還這么高?
面試官在問了上兩次提到的問題之后,可能就會開始更加猛烈的攻勢,一連串的Redis的知識點向你拋過來,你頂的住嗎?
下面就面試經常問到的問題,以問答的方式分享給大家。
Redis如何保證高並發,高可用?
高並發:
redis的單機吞吐量可以達到幾萬不是問題,如果想提高redis的讀寫能力,可以用redis的主從架構,redis天熱支持一主多從的准備模式,單主負責寫請求多從負責讀請求,主從之間異步復制,把主的數據同步到從。
高可用:
首先利用redis的主從架構解決redis的單點故障導致的不可用,然后如果使用的是主從架構,那么只需要增加哨兵機制即可,就可以實現,redis主實例宕機,自動會進行主備切換。以此來達到redis的高可用。
你剛才說主從復制,那你能具體聊一下主從復制的原理嗎?
在redis主從架構中,master負責接收寫請求,寫操作成功后返回客戶端OK,然后后將數據異步的方式發送給多個slaver進行數據同步,不過從redis 2.8開始,slave node會周期性地確認自己每次復制的數據量。
當啟動一個slave node的時候,它會發送一個PSYNC
命令給master node。如果slave node是重新連接master node,那么master node僅僅會復制給slave部分缺少的數據; 否則如果是slave node第一次連接master node,那么會觸發一次full resynchronization
全量復制。
開始full resynchronization
的時候,master會啟動一個后台線程,開始生成一份RDB快照文件,同時還會將從客戶端收到的所有寫命令緩存在內存(內存緩沖區)中。RDB文件生成完畢之后,master會將這個RDB發送給slave,slave會先寫入本地磁盤,然后再從本地磁盤加載到內存中。然后master會將內存中緩存的寫命令發送給slave,slave也會同步這些數據。
另外slave node做復制的時候,是不會block master node的正常工作的,也不會block對自己的查詢操作,它會用舊的數據集來提供服務; 但是復制完成的時候,需要刪除舊數據集,加載新數據集,這個時候就會暫停對外服務了。slave node主要用來進行橫向擴容,做讀寫分離,擴容的slave node可以提高讀的吞吐量。slave與高可用性有很大的關系。
Tips:邊講邊畫圖最好了。
主從復制的過程中如果因為網絡原因停止復制了會怎么樣?
如果出現網絡故障斷開連接了,會自動重連的,從redis 2.8開始,就支持主從復制的斷點續傳,可以接着上次復制的地方,繼續復制下去,而不是從頭開始復制一份。
master如果發現有多個slave node都來重新連接,僅僅會啟動一個rdb save操作,用一份數據服務所有slave node。
master node會在內存中創建一個backlog
,master和slave都會保存一個replica offset
,還有一個master id
,offset就是保存在backlog中的。如果master和slave網絡連接斷掉了,slave會讓master從上次的replica offset開始繼續復制。
但是如果沒有找到對應的offset,那么就會執行一次resynchronization
全量復制。
好的,那你能說說什么是哨兵有什么作用嗎?
哨兵是redis集群架構中非常重要的一個組件,主要功能如下
(1)集群監控,負責監控redis master和slave進程是否正常工作
(2)消息通知,如果某個redis實例有故障,那么哨兵負責發送消息作為報警通知給管理員
(3)故障轉移,如果master node掛掉了,會自動轉移到slave node上
(4)配置中心,如果故障轉移發生了,通知client客戶端新的master地址
哨兵本身也是分布式的,作為一個哨兵集群去運行,互相協同工作
(1)故障轉移時,判斷一個master node是宕機了,需要大部分的哨兵都同意才行,涉及到了分布式選舉的問題
(2)即使部分哨兵節點掛掉了,哨兵集群還是能正常工作的,因為如果一個作為高可用機制重要組成部分的故障轉移系統本身是單點的,那就很坑爹了。
目前采用的是sentinal 2版本,sentinal 2相對於sentinal 1來說,重寫了很多代碼,主要是讓故障轉移的機制和算法變得更加健壯和簡單。
為什么redis哨兵集群只有2個節點無法正常工作?
如果兩個哨兵實例,即兩個redis實例,一主一從的模式。
則redis的配置quorum=1,表示一個哨兵認為master宕機即可認為master已宕機。
但是如果是機器1宕機了,那哨兵1和master都宕機了,雖然哨兵2知道master宕機了,但是這個時候,需要majority,也就是大多數哨兵都是運行的,2個哨兵的majority就是2(2的majority=2,3的majority=2,5的majority=3,4的majority=2),2個哨兵都運行着,就可以允許執行故障轉移。
但此時哨兵1沒了就只有1個哨兵了了,此時就沒有majority來允許執行故障轉移,所以故障轉移不會執行。
主備切換的時候會有數據丟失的可能嗎?
會有,而且有兩種可能,一種是異步復制,一種是腦裂導致的數據丟失。
簡單描述一下這兩種數據丟失的過程吧
好的,第一種很好理解,因為master 到 slave的復制是異步的,所以可能有部分數據還沒復制到slave的時候,master就宕機了,此時這些部分數據就丟失了。雖然master會做持久化,但是哨兵將slave提升為master后,如果舊的master這時候好了,會當做slave掛到新的master上,從新的master同步數據,原來的數據還是會丟失。
第二種,也就是說,某個master所在機器突然脫離了正常的網絡,跟其他slave機器不能連接,但是實際上master還運行着,即集群分區現象。此時哨兵可能就會認為master宕機了,然后開啟選舉,將其他slave切換成了master.
這個時候,集群里就會有兩個master,也就是所謂的腦裂。
此時雖然某個slave被切換成了master,但是可能client還沒來得及切換到新的master,還繼續向舊master寫數據,這部分數據可能就丟失了。因此舊master再次恢復的加入到主從結構中時,會被作為一個slave掛到新的master上去,自己的數據會清空,重新從新的master復制數據,原來的寫到舊master的數據就丟失了。
那有什么辦法解決這個數據丟失的問題嗎?
數據丟失的問題是不可避免的,但是我們可以盡量減少。
在redis的配置文件里設置參數
min-slaves-to-write 1
min-slaves-max-lag 10
min-slaves-to-write
默認情況下是0,min-slaves-max-lag
默認情況下是10。
上面的配置的意思是要求至少有1個slave,數據復制和同步的延遲不能超過10秒。如果說一旦所有的slave,數據復制和同步的延遲都超過了10秒鍾,那么這個時候,master就不會再接收任何請求了。
上面兩個配置可以減少異步復制和腦裂導致的數據丟失。
設置了這倆參數具體是怎么減少數據丟失的呢?
以上面配置為例,這兩個參數表示至少有1個salve的與master的同步復制延遲不能超過10s,一旦所有的slave復制和同步的延遲達到了10s,那么此時master就不會接受任何請求。
我們可以減小min-slaves-max-lag
參數的值,這樣就可以避免在發生故障時大量的數據丟失,一旦發現延遲超過了該值就不會往master中寫入數據。
那么對於client,我們可以采取降級措施,將數據暫時寫入本地緩存和磁盤中,在一段時間后重新寫入master來保證數據不丟失;也可以將數據寫入kafka消息隊列,隔一段時間去消費kafka中的數據。
通過上面兩個參數的設置我們盡可能的減少數據的丟失,具體的值還需要在特定的環境下進行測試設置。
好的,今天回答的還不錯,下一輪面試繼續努力哦~
面試官顯然對你今天的回答比較滿意,已經邀請你下一輪面試了~~~
手機閱讀的用戶可移至公眾號哦,更方便
本系列文章在於面試突擊,不是教程,要是細挖,能講好多,而面試你只需要把這個原理說出來就行了,如果邊講邊畫圖那就更好了。
該系列文章在於快速突擊,快速拾遺,溫習。