1. 程式人生 > >《【面試突擊】— Redis篇》-- Redis哨兵原理及持久化機制

《【面試突擊】— Redis篇》-- Redis哨兵原理及持久化機制

能堅持別人不能堅持的,才能擁有別人未曾擁有的。
關注程式設計大道公眾號,讓我們一同堅持心中所想,一起成長!!

《【面試突擊】— Redis篇》-- Redis哨兵原理及持久化機制

在這個系列裡,我會整理一些面試題與大家分享,幫助年後和我一樣想要在金三銀四準備跳槽的同學。
我們一起鞏固、突擊面試官常問的一些面試題,加油!!

《【面試突擊】— Redis篇》--Redis資料型別?適用於哪些場景?

《【面試突擊】— Redis篇》--Redis的執行緒模型瞭解嗎?為啥單執行緒效率還這麼高?

《【面試突擊】— Redis篇》-- Redis的主從複製?哨兵機制?

前兩次因為時間原因面試官暫時中止了面試,覺得上次你對redis的主從複製,哨兵機制的知識掌握的還可以,於是今天面試官想看看你到底對Redis瞭解有多深,又加大了攻勢,你準備好了嗎?

上次因為時間問題面試草草收場今天我還有幾個哨兵的問題要問。首先說一下Redis Sentinel是怎麼工作的?重點描述一下故障轉移的過程

好的。

1)每個Sentinel以每秒鐘一次的頻率向它所知的Master,Slave以及其他 Sentinel 例項傳送一個 PING 命令。

2)如果一個例項(instance)距離最後一次有效回覆 PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 則這個例項會被當前 Sentinel 標記為主觀下線。

3)如果一個Master被標記為主觀下線,則正在監視這個Master的所有 Sentinel 要以每秒一次的頻率確認Master的確進入了主觀下線狀態。

4)當有足夠數量的 Sentinel(大於等於配置檔案指定的值)在指定的時間範圍內確認Master的確進入了主觀下線狀態, 則Master會被標記為客觀下線 。

5)當Master被 Sentinel 標記為客觀下線時,Sentinel 向下線的 Master 的所有 Slave 傳送 INFO 命令的頻率會從 10 秒一次改為每秒一次 (在一般情況下, 每個 Sentinel 會以每 10 秒一次的頻率向它已知的所有Master,Slave傳送 INFO 命令 )。

6)若沒有足夠數量的 Sentinel 同意 Master 已經下線, Master 的客觀下線狀態就會變成主觀下線。 若 Master 重新向 Sentinel 的 PING 命令返回有效回覆, Master 的主觀下線狀態就會被移除。

7)sentinel節點會與其他sentinel節點進行“溝通”,投票選舉一個sentinel節點進行故障處理,在從節點中選取一個主節點,其他從節點掛載到新的主節點上自動複製新主節點的資料。

故障轉移時會從剩下的slave選舉一個新的master,被選舉為master的標準是什麼?

如果一個master被認為odown了,而且majority哨兵都允許了主備切換,那麼某個哨兵就會執行主備切換操作,此時首先要選舉一個slave來,會考慮slave的一些資訊。
(1)跟master斷開連線的時長。
如果一個slave跟master斷開連線已經超過了down-after-milliseconds的10倍,外加master宕機的時長,那麼slave就被認為不適合選舉為master.

( down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state

(2)slave優先順序。
按照slave優先順序進行排序,slave priority越低,優先順序就越高

(3)複製offset。
如果slave priority相同,那麼看replica offset,哪個slave複製了越多的資料,offset越靠後,優先順序就越高

(4)run id
如果上面兩個條件都相同,那麼選擇一個run id比較小的那個slave

執行切換的那個哨兵在完成故障轉移後會做什麼?

會進行configuraiton配置資訊傳播。

哨兵完成切換之後,會在自己本地更新生成最新的master配置,然後通過pub/sub訊息機制同步給其他的哨兵。

同步配置的時候其他哨兵根據什麼更新自己的配置呢?

執行切換的那個哨兵,會從要切換到的新master(salve->master)那裡得到一個configuration epoch,這就是一個version號,每次切換的version號都必須是唯一的。

如果第一個選舉出的哨兵切換失敗了,那麼其他哨兵,會等待failover-timeout時間,然後接替繼續執行切換,此時會重新獲取一個新的configuration epoch 作為新的version號。

這個version號就很重要了,因為各種訊息都是通過一個channel去釋出和監聽的,所以一個哨兵完成一次新的切換之後,新的master配置是跟著新的version號的,其他的哨兵都是根據版本號的大小來更新自己的master配置的。

好,上次哨兵的問題暫時就到這吧,接下來說說redis的持久化方面的問題吧。首先,生產上Redis要不要持久化?如果要,說說為什麼需要,或者說持久化對生產系統的意義何在?

要。

redis持久化主要是做災難恢復,資料恢復,也可以歸類到高可用的範疇。

比如Redis整個掛了,導致Redis不可用了,這時候首先要做的事情是讓Redis儘快變得可用。那麼就會去重啟Redis,儘快讓它對外提供服務。但是如果沒做持久化沒有資料備份,這個時候Redis啟動了,也不可用啊,資料都沒了!

這時候很可能,大量的請求過來,在快取全部無法命中,這個時候就死定了,可能會導致快取雪崩問題,所有的請求,沒有在Redis命中,就會去資料庫中去找,資料庫一下子承接高併發,然後就掛了。資料庫掛掉,你都沒法去找資料恢復到redis裡面去。

Redis持久化機制有哪些?

Redis有兩種持久化機制,AOF和RDB。

AOF,記錄每次寫請求的命令,以追加的方式在檔案尾部追加,直接在尾部追加,效率比較高。
對於作業系統來說,不是每次寫都直接寫到磁碟,作業系統自己會有一層cache,redis寫磁碟的資料會先快取在os cache裡,redis每隔1秒呼叫一次作業系統的fsync操作,強制將os cache中的資料刷入AOF檔案中。

當redis重啟的時候,就把AOF中記錄的命令重新執行一遍就可以了,但是如果檔案很大的話,執行會耗費較多的時間,對於資料恢復來說耗時會多一點。

RDB,是快照檔案,每隔一定時間將redis記憶體中的資料生成一份完整的RDB快照檔案,當redis重啟的時候直接載入資料即可,同樣的資料比AOF恢復的要快。

說說這兩種持久化機制各自的特點、優缺點吧

好的。
RDB的優點
第一點就是他會生成多個數據檔案,每個資料檔案都代表了某一時刻redis中的資料,非常適合做冷備。
第二點,RDB持久化機制對redis對外提供的讀寫服務影響非常小,可以讓redis保持高效能,因為redis主程序只需要fork一個子程序,讓子程序執行磁碟IO操作來進行RDB持久化即可。
第三點,相對於AOF持久化機制來說,直接基於RDB資料檔案來重啟和恢復redis程序,更加快速。

AOF,存放的指令日誌,做資料恢復的時候,其實是要回放和執行所有的指令日誌,來恢復出來記憶體中的所有資料的。

RDB,就是一份資料檔案,恢復的時候,直接載入到記憶體中即可。

RBD的缺點
1)故障時可能資料丟失的比AOF要多。
一般來說,RDB資料快照檔案,都是每隔5分鐘或者更長時間生成一次,這個時候一旦redis程序宕機,那麼會丟失最近5分鐘的資料。

這個問題,也是rdb最大的缺點,就是不適合做第一優先的恢復方案,如果你依賴RDB做第一優先恢復方案,會導致資料丟失的比較多

2)RDB每次在fork子程序來執行RDB快照資料檔案生成的時候,如果資料檔案特別大,可能會導致對客戶端提供的服務暫停數毫秒,或者甚至數秒。

所以一般不要讓RDB的間隔太長,否則每次生成的RDB檔案太大了,對redis本身的效能可能會有影響的。

AOF的優點

1)AOF可以更好的保護資料不丟失
一般AOF會每隔1秒,通過一個後臺執行緒執行一次fsync操作,最多丟失1秒鐘的資料。

每隔1秒,就執行一次fsync操作,保證os cache中的資料寫入磁碟中。
redis程序掛了,最多丟掉1秒鐘的資料.

2)AOF持久化效能高
AOF日誌檔案以append-only模式寫入,所以沒有任何磁碟定址的開銷,寫入效能非常高,而且檔案不容易破損,即使檔案尾部破損,也很容易修復。

3)AOF日誌檔案即使過大的時候,出現後臺重寫操作,也不會影響客戶端的讀寫。
因為在rewrite log的時候,會對其中的指令進行壓縮,創建出一份需要恢復資料的最小日誌出來。再建立新日誌檔案的時候,老的日誌檔案還是照常寫入。當新的merge後的日誌檔案ready的時候,再交換新老日誌檔案即可。

4)AOF日誌檔案的命令通過非常可讀的方式進行記錄,這個特性非常適合做災難性的誤刪除的緊急恢復。

比如某人不小心用flushall命令清空了所有資料,只要這個時候後臺rewrite還沒有發生,那麼就可以立即拷貝AOF檔案,將最後一條flushall命令給刪了,然後再將該AOF檔案放回去,就可以通過恢復機制,自動恢復所有資料。

AOF的缺點

(1)對於同一份資料來說,AOF日誌檔案通常比RDB資料快照檔案更大

(2)AOF開啟後,支援的寫QPS會比RDB支援的寫QPS低,因為AOF一般會配置成每秒fsync一次日誌檔案,當然,每秒一次fsync,效能也還是很高的。

如果你要保證一條資料都不丟,也是可以的,AOF的fsync設定成沒寫入一條資料,fsync一次,但是那樣導致redis的QPS大幅度下降。

(3)以前AOF發生過bug,就是通過AOF記錄的日誌,進行資料恢復的時候,沒有恢復一模一樣的資料出來。

所以說,類似AOF這種較為複雜的基於命令日誌/merge/回放的方式,比基於RDB每次持久化一份完整的資料快照檔案的方式,更加脆弱一些,容易有bug。

 

不過AOF就是為了避免rewrite過程導致的bug,因此每次rewrite並不是基於舊的指令日誌進行merge的,而是基於當時記憶體中的資料進行指令的重新構建,這樣健壯性會好很多。

(4)唯一的比較大的缺點,其實就是做資料恢復的時候,會比較慢,做冷備不太合適。

你剛才提到冷備,那你具體說說為啥AOF不適合RDB適合?

其實兩個都可以做,只不過RDB更適合。

RDB可以做冷備,是因為它會生成多個檔案,每個檔案都代表了某一個時刻的完整的資料快照,我們可以將這種完整的資料檔案傳送到一些遠端的安全儲存上去,比如可以是阿里雲的ODPS分散式儲存上,以預定好的備份策略來定期備份redis中的資料。

AOF也可以做冷備,只不過它只有一個檔案,但是我們可以去自己寫程式,每隔一定時間,去copy一份這個檔案出來。

RDB做冷備,優勢在於由redis去控制固定時長生成快照檔案的事情,比較方便,而 AOF,還需要我們自己寫一些指令碼去做這個事情,各種定時,比較麻煩。

RDB資料做冷備,在最壞的情況下,提供資料恢復的時候,速度比AOF快。

說了那麼多AOF和RDB,那麼生產系統對於這倆持久化機制到底該如何選擇呢?

至於,RDB和AOF到底該如何選擇,我覺得兩種都選擇,

1)不要僅僅使用RDB,因為那樣會導致你丟失很多資料。

2)也不要僅僅使用AOF,因為那樣有兩個問題,

  • 第一,你通過AOF做冷備,沒有RDB做冷備,來的恢復速度更快;
  • 第二,RDB每次簡單粗暴生成資料快照,更加健壯,可以避免AOF這種複雜的備份和恢復機制的bug。

3)綜合使用AOF和RDB兩種持久化機制,用AOF來保證資料不丟失,作為資料恢復的第一選擇; 用RDB來做不同程度的冷備,在AOF檔案都丟失或損壞不可用的時候,還可以使用RDB來進行快速的資料恢復,作為資料恢復的最後一道防線。

好,今天就到這裡,下次我們繼續聊

終於結束了。

其實如果你的簡歷上寫了掌握Redis,那麼如果面試官也比較精通Redis的話,他就會抓住你這一個Redis從淺入深的一直追著問,看看你到底對Redis瞭解多少,是不是平時自己真的積累過這些知識,是不是比別人要懂得多一點,經過一層一層的深挖,看看你能過幾關。相對於其他競爭者可能幾個回合就招架不住了,你要是能多戰幾個回合,面試官對你的印象也會越深,你的機會也就越大。

如果說就redis問你幾個基礎的問題,那面試官要麼對redis瞭解不多,要麼就看中了你簡歷中的其他亮點。

本系列文章在於面試突擊,不是教程,要是細挖能講好多,而面試你只需要把這個原理說出來就行了,如果邊講邊畫圖那就更好了。

該系列文章在於快速突擊,快速拾遺,溫習。