redis學習筆記-複製、sentinel與集羣

複製

咱們能夠執行SLAVEOF命令或者設置slaveof選項,讓一個服務器去複製(replicate)另外一個服務器,複製數據的服務器會變成另外一臺服務器的從服務器,兩者保持相同的數據。之後在主服務器上設置鍵值會自動同步數據到從服務器上。node

複製功能的實現

同步

將從服務器的數據庫狀態更新至主服務器當前所處的數據庫狀態。redis

clipboard.png

命令傳播

當主服務器的數據庫狀態被修改,致使主從服務器的數據庫狀態出現不一致時,讓主從服務器的數據庫從新回到一致狀態。
在命令傳播階段,從服務器默認會以每秒一次的頻率,向主服務器發送命令:數據庫

REPLICATION ACK <replication_offset>

主要用於檢測主從服務器的網絡鏈接狀態和命令丟失。服務器

sentinel(redis高可用解決方案)

由一個或多個sentinel實例組成的sentinel系統能夠監視任意多個主服務器,以及這些主服務器屬下的全部從服務器;並在被監視的主服務器進入下線狀態時,自動將下線主服務器屬下的某個從服務器升級爲新的主服務器,而後由新的主服務器代替已下線的主服務器繼續處理命令請求。如圖所示:網絡

clipboard.png

它是如何工做的?

啓動

redis-sentinel sentinel.conf 或者
redis-server sentinel.conf --sentinel

初始化服務器

sentinel本質上只是一個運行在特殊模式下的redis服務器,但它不使用數據庫,因此並不會載入RDB文件或者AOF文件來還原數據庫狀態。初始化過程:異步

  • 使用sentinel專用代碼初始化sentinel狀態分佈式

  • 建立連向主服務器的網絡鏈接spa

鏈接創建以後,sentinel將成爲主服務器的客戶端,它能夠向主服務器發送命令,並從命令回覆中獲取相關的信息。對於每一個被sentinel監視的主服務器來講,sentinel會建立兩個連向主服務器的異步網絡鏈接:設計

  • 命令鏈接,向主服務發送命令,並接收命令回覆code

  • 訂閱鏈接,訂閱主服務器的__sentinel__:hello頻道

注:若是發現主服務器下有從服務器,也會爲從服務器建立命令鏈接和訂閱鏈接。而sentinel與sentinel之間則只建立命令鏈接。

獲取服務器信息

sentinel默認會以每十秒一次的頻率,經過命令鏈接向被監視的主從服務器發送INFO命令,並經過分析INFO命令的回覆來獲取主服務器的當前信息。

發送和接收消息

在默認狀況下,sentinel會以每兩秒一次的頻率,經過命令鏈接向全部被監視的主服務器和從服務器發送如下格式的命令:

PUBLISH __sentinel__:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>"

當sentinel與一個主服務器或者從服務器創建起訂閱鏈接以後,sentinel就會經過訂閱鏈接,向服務器發送如下命令:

SUBSCRIBE __sentinel__:hello

sentinel對__sentinel__:hello頻道的訂閱會一直持續到sentinel與服務器的鏈接斷開爲止。

也就是說,對於每一個與sentinel鏈接的服務器,既經過命令鏈接向服務器的__sentinel__:hello頻道發送信息,又經過訂閱鏈接從服務器的__sentinel__:hello頻道接收信息。對於監視同一個服務器的多個sentinel來講,一個sentinel發送的信息會被其餘sentinel接收到,這些信息會被用於更新其餘sentinel對發送信息sentinel的認知,也會被用於更新其餘sentinel對被監視服務器的認知。

檢測服務器狀態

檢測主觀下線狀態

sentinel以每秒一次的頻率向實例(包括主服務器、從服務器、其餘sentinel)發送PING命令,並根據實例對PING命令的回覆來判斷實例是否在線,當一個實例在指定的時長中連續向sentinel發送無效回覆時,sentinel會將這個實例判斷爲主觀下線。

檢測客觀下線狀態,進行故障轉移

當sentinel將一個主服務器判斷爲主觀下線時,它會向一樣監視這個主服務器的其餘sentinel進行詢問,看它們是否贊成這個主服務器已經進入主觀下線狀態;當sentinel收集到足夠多的主觀下線投票以後,它會將主服務器判斷爲客觀下線,並選取一個領頭sentinel發起一次針對主服務器的故障轉移操做。
注:更多細節請查閱<<redis設計與實現>> 第16章內容...

集羣

redis集羣是redis提供的分佈式數據庫方案,集羣經過分片(sharding)來進行數據共享,並提供複製和故障轉移功能(redis3.0以前須要依靠client端作sharding,3.0以後,開始支持server端的集羣)。

節點

一個redis集羣由多個節點(node)組成,使用cluster meet ip port鏈接各個節點(握手),而後經過cluster nodes查看集羣節點信息。

  • 啓動服務器的時候會判斷cluster-enabled值:若是爲yes,開啓服務器的集羣模式成爲一個節點。

  • 節點分爲主節點和從節點,主節點用於處理槽(有關槽的介紹見下一小節),而從節點用於複製某個主節點,並在被複制的主節點下線時,代替下線主節點繼續處理命令請求(集羣中的每一個節點都會按期地向集羣中其餘節點發送PING消息,以此來檢測對方是否在線)。

注:節點和單機服務器在數據庫方面的一個區別是,節點只能使用0號數據庫,而單機redis服務器則沒有這一限制。

槽指派

redis集羣經過分片的方式來保存數據庫中的鍵值對:集羣的整個數據庫被分爲16384個槽(slot),數據庫中的每一個鍵都屬於這16384個槽的其中一個,集羣中的每一個節點能夠處理0個或最多16384個槽。

  1. 經過向節點發送CLUSTER ADD SLOTS命令, 咱們能夠將一個或多個槽指派(assign)給某個節點負責,好比將槽0至5000指派給節點7000負責:
    127.0.0.1:7000> CLUSTER ADDSLOTS 0 1 2 3 4 ... 5000

  2. 每一個節點都會記錄哪些槽指派給了本身,而哪些槽又被指派給了其餘節點。當數據庫中的16384個槽都有節點在處理時,集羣處於上線狀態(ok);相反地,若是數據庫中有任何一個槽沒有獲得處理,那麼集羣處於下線狀態(fail)。

分片:將你的數據拆分到多個redis實例的過程,這樣每一個實例將只包含全部鍵的子集。經過多臺服務器實現分片,能夠再也不侷限於單機所能支持的內存容量,利於擴展。另外,因爲每一個key最終只會存儲到一個特定的redis實例的一個slot中,若是要實現高可用,最好至少保證雙寫,一個key要存儲到兩個redis實例中(對應兩臺服務器),讀取的時候能夠隨機讀。

在集羣中執行命令過程

clipboard.png

從新分片

redis集羣的從新分片操做能夠將任意數量已經指派給某個節點(源節點)的槽改成指派給另外一個節點(目標節點),而且相關槽所屬的鍵值對也會從源節點被移動到目標節點。從新分片操做能夠在線(online) 進行,在從新分片的過程當中,集羣不須要下線,而且源節點和目標節點均可以繼續處理命令請求。對集羣中單個槽從新分片須要執行以下命令:

目標節點:CLUSTER SETSLOT <slot> IMPORTING <source_id> ①
源節點:CLUSTER SETSLOT <slot> MIGRATING <target_id> ②
源節點:CLUSTER GETKEYSINSLOT <slot> <count> ③
源節點:MIGRATE <target_ip> <target_port> <key_name> 0 <timeout> ④
任意節點:CLUSTER SETSLOT <slot> NODE <target_id> 通知其它節點該槽指派給了target_id節點

注:從新分片是基於鍵值對維度的,每一個槽中的n個鍵須要執行n次③和④的操做。

相關文章
相關標籤/搜索