1. 程式人生 > >redis知識盤點【肆】_主從複製和sentinel哨兵

redis知識盤點【肆】_主從複製和sentinel哨兵

在進入正題之前,我們先明確兩個概念:叢集和分散式。在移動網際網路專案中這兩個詞語經常一起出現,不少人也認為其表達的一個意思,但是並不是的。按我的理解,叢集就是一組伺服器,每臺伺服器的內容或資料都是一致的;分散式也是一組伺服器,但是每臺伺服器的內容或資料是按照業務或其他規則切分過的,所有伺服器加起來的整體才擁有完整的內容或資料。

我想了個例子不知恰當與否,以《西遊記》的場景為例,叢集就像是孫悟空拔下猴毛吹出的千百隻和他一模一樣的猴子,其實孫悟空相當於主機(master),那些猴子相當於從機(slaves),他們的所有一切是一模一樣的;而分散式相當於取經四人小團隊,有負責挑擔的有負責牽馬的,有負責被妖怪抓(同樣有意義,不然湊不夠八十一難)也有負責打怪的,每個人各司其職,加起來的整體完成了取經的這個功能。

說回redis,在此係列的第一篇文章中也有提到,redis分別於2.8和3.0版本推出了sentinel(哨兵)和cluster(叢集)功能。sentinel是解決HA問題的,即雙機叢集;而cluster是解決資料sharding問題的,即分散式快取。這兩個功能不重複,並且經常一起使用。sentinel哨兵功能是應用在redis主從複製基礎之上的,這裡先介紹下redis的主從複製功能。

在redis中我們可以通過在.conf中配置salveof引數,讓一臺redis伺服器去複製(replicate)另一個redis伺服器,此時前一臺伺服器為主伺服器,後一臺為從伺服器。主伺服器和從伺服器的資料是完全一樣的,一臺主伺服器可以有多臺從伺服器。redis對資料複製功能的實現在2.8版本之前和之後也是不一樣的。

在redis 2.8版本之前,主從同步主要是通過從伺服器向主伺服器傳送sync命令實現的:主伺服器接收到sync命令後自動執行bgsave命令,生成一個RDB檔案,並使用一個緩衝區儲存從當前開始的所有寫命令,生成完畢後將這個RDB檔案傳送給從伺服器,從伺服器接收並載入,將自己的資料庫狀態更新為主伺服器執行bgsave命令時的資料庫狀態,之後再接收執行主伺服器傳送過來的緩衝區中儲存的寫命令,實現了和主伺服器當前狀態的一致。

2.8版本之前複製功能的缺陷:如果在複製過程中斷線了,那麼下次複製的時候會完全從頭複製。因為生成RDB檔案耗費主伺服器的CPU、記憶體和磁碟資源;傳送RDB檔案也會佔用大量的網路頻寬,因此這樣的做法是非常低效的。好在2.8版本之後redis做了優化,使用psync命令替代了sync命令,區別在於,psync

支援完整重同步和部分重同步兩種 模式。主要說部分重同步,redis伺服器維護了複製積壓緩衝區、複製偏移量和伺服器執行id三個元素。當該伺服器為主機時,複製積壓緩衝區會儲存最近的寫命令,每條命令對應一個複製偏移量,當進行復制時,主伺服器會將最新執行的命令的複製偏移量同步給從伺服器,如果複製中斷後再複製,從伺服器可先根據伺服器執行id找到當時複製的主伺服器,再根據複製偏移量找到上次中斷的命令,進行繼續複製。

站在主從複製的基礎上,下面說說sentinel哨兵的實現。

redis sentinel包含若干個sentinel節點和redis資料節點,每個sentinel節點會對資料節點和其餘sentinel節點進行監控,當它發現節點不可達時,會對節點做下線標識。如果被標識的是主節點,它還會和其他sentinel節點進行"協商",當大多數sentinel節點都認為主節點不可達時,它們會選舉出一個從節點來完成自動故障轉移的工作,同時會將這個變化實時通知給redis應用方。後面如果已下線主節點恢復正常,會將其作為新主節點的從節點重新上線。整個過程完全是自動的,不需要人工來介入,所以這套方案很有效地解決了redis的高可用問題。

sentinel本質上只是一個執行在特殊模型下的redis伺服器,初始化sentinel時不會載入RDB或AOF檔案。sentinel會建立到主伺服器的命令連線和訂閱連線,預設以每十秒一次的頻率通過命令連線向被監視的主伺服器傳送INFO命令,通過分析INFO命令的回覆來獲取主伺服器的的所有從伺服器資訊。當sentinel發現主伺服器有新的從伺服器出現時,sentinel除了會為這個新的從伺服器建立相應的例項結構外,還會建立連線到從伺服器的命令連線和訂閱連線。同主伺服器一樣,sentinel也會預設以每十秒一次的頻率通過命令連線向從伺服器傳送INFO命令。

對於監視同一個主伺服器和從伺服器的多個sentinel來說,他們之間只建立命令連線,以2秒1次的頻率通過向被監視伺服器的_sentinel_:hello頻道互相通訊。

sentinel還會以每秒一次的頻率向其他伺服器例項(主伺服器、從伺服器和sentinel例項)傳送ping命令,並根據回覆判斷例項是否線上,當超過一定時間沒有回覆則會同sentinel投票判斷其認為下線,當超過指定票數則投票通過。生產環境中,建議redis sentinel的所有節點部署在不同物理機上,sentinel應該部署奇數個。

sentinel在.conf中的重要配置項:

sentinel monitor mymaster 127.0.0.1 6379 quorum:quorum為投票時通過的票數

sentinel auth-pass mymaster password:主機的認證密碼

sentinel down-after-milliseconds mymaster 5000ping,5000ms後認為宕機
sentinel parallel-syncs mymaster num當mymaster掛了後,num臺從機向新的主機複製操作
sentinel failover-timeout mymaster times通常被解釋成故障轉移超時時間,但實際上它作用於故障轉移的各個階段:
    a)選出合適從節點。
    b)晉升選出的從節點為主節點。
    c)命令其餘從節點複製新的主節點。
    d)等待原主節點恢復後命令它去複製新的主節點。
failover-timeout的作用具體體現在四個方面:
1)如果Redis sentinel對一個主節點故障轉移失敗,那麼下次再對該主節點做故障轉移的起始時間是failover-timeout的2倍。
2)在b)階段時,如果sentinel節點向a)階段選出來的從節點執行slaveof no one —直失敗(例如該從節點此時出現故障),當此過程超過failover-timeout時,則故障轉移失敗。
3)在b)階段如果執行成功,sentinel節點還會執行info命令來確認a)階段選出來的節點確實晉升為主節點,如果此過程執行時間超過failover-timeout時,則故障轉移失敗。
4)如果c)階段執行時間超過了failover-timeout(不包含複製時間),則故障轉移失敗注意及時超過了這個時間,sentinel節點也會最終配置從節點去同步最新的主節點。


sentinel功能的介紹先到這,下一篇文章介紹一下redis的cluster功能。