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
站在主從複製的基礎上,下面說說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 5000:ping,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功能。