Redis 可使用從屬服務器來實現讀寫分離提升吞吐量或在主服務器故障時接替主服務器以提升可用性。redis
每一個 Redis 服務器實例均可以配置多個 slave 節點,slave 服務器也能夠擁有次級 slave 節點, 能夠組織成複雜的樹狀結構(雖然說生產環境下極少有人這麼作)。算法
爲了嘗試配置主從複製,咱們至少須要兩個 redis 服務器實例。最簡單的方法是在 redis 官網下載 redis-server 二進制可執行文件,分別放在 master 和 slave 目錄中。bash
在每一個目錄中分別建立 redis.conf 配置文件。master 實例的配置文件採用默認便可, 在 slave 實例中進行主從複製配置:服務器
# 和主服務器 6379 區分 port 6380 # 主服務器 ip 端口 slaveof 127.0.0.1 6379 # 若是主服務器配置了密碼請寫在這個配置項中 # masterauth <master-password> ## ## 接下來的選項保留默認配置便可,這裏僅作介紹 ## # 當與 master 斷開鏈接或正在進行同步時 # yes: 仍然正常響應客戶端請求,但可能返回過期數據 # no: 除 INFO 和 SLAVEOF 命令正常外,其它命令均返回 SYNC with master in progress 錯誤 slave-serve-stale-data yes # 從服務器只讀 slave-read-only yes
使用redis-server redis.conf
命令分別啓動 redis-server 實例。 使用redis-cli -p 6380
命令鏈接從服務器:網絡
127.0.0.1:6380> info Replication # Replication role:slave master_host:127.0.0.1 master_port:6379 master_link_status:up master_last_io_seconds_ago:16 master_sync_in_progress:0 slave_repl_offset:3640 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:0b4e100aa9e9fda54aeba2bc110316d811ac2ff6 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:3640 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:3640 127.0.0.1:6380> get a 1 127.0.0.1:6380> set a 2 (error) READONLY You can't write against a read only slave.
SLAVEOF host port
能夠動態改變從服務器所屬的 master 節點。SLAVEOF NO ONE
關閉複製功能,並從 slave 服務器轉變回 master 服務器,原來同步所得的數據集不會被丟棄。在當主服務器故障時,可使用SLAVEOF NO ONE
命令將 slave 服務器提高爲 master。架構
在 Redis 2.8 以前的版本里,Redis 僅支持全量複製不支持增量複製,這極大的影響了主從同步的性能。性能
Redis 2.8 以前的版本主從複製流程以下:code
Redis 2.8 開始使用 PSYNC 命令代替 SYNC 命令, PSYNC 具備全量複製和增量複製功能。server
master 和 slave 節點均擁有一個 runid 做爲本身的惟一標識。ip
master 和 slave 會各自維護一個複製偏移量,在增量複製時標識同步進度。
master 會維護一個 FIFO 的複製緩衝區(replication backlog),默認大小 1mb。
# 複製緩衝區大小 repl-backlog-size 1mb # 當 master 再也不與任何 slave 保持鏈接時,複製緩衝區可能被清空 # repl-backlog-ttl 用於配置從斷開鏈接到清空緩衝區間隔的秒數 # 0 表示永不清除緩衝區 repl-backlog-ttl 3600
接下來咱們能夠開始說明 PSYNC 命令執行的流程:
PSYNC ? -1
命令要求進行全量同步。psync <runid> <offset>
命令要求增量同步,其中 runid 是上次同步的主服務器的ID,offset 是同步偏移量+continue
將複製緩衝區內的數據同步到 slave+fullresync <runid> <offset>
執行全量同步,其中 runid 是自身ID, offset 是自身同步偏移量。PSYNC
命令則響應 error, slave 會嘗試使用 SYNC 命令進行同步。簡單的主從複製架構在 master 故障後會不可用,Redis 官方提供了哨兵(sentinel)機制自動實現主備切換保證高可用。
哨兵機制經過一組哨兵節點監控主從節點的運行狀態,並在主節點故障後選舉新的主節點。
哨兵節點定時執行3個任務:
哨兵節點每隔10s向主從節點發送INFO
命令以更新拓撲圖,自動感知新的 slave 節點。
哨兵節點每隔1s向主從節點發送PING
命令進行心跳檢測。
哨兵節點每隔2s向__sentinel__:hello
頻道發送自身哨兵節點信息和自身瞭解的 master 信息。全部哨兵節點均會訂閱該頻道,並以此更新哨兵集羣信息。
若哨兵節點發現 master 節點心跳響應超時,則認爲 master 主觀下線。此時,master 可能真的已經崩潰也可能僅僅是此哨兵節點與 master 之間出現網絡故障。
認爲 master 主觀下線的哨兵會向其它哨兵發送sentinel is-master-down-by addr
詢問 master 是否下線。若半數以上的哨兵認爲 master 已經下線則認爲 master 客觀下線。
哨兵節點會選舉本身第一個收到的 is-master-down-by 命令的發送者爲哨兵領導者。若某一個節點獲得過半投票則會成爲哨兵領導者,若沒有節點獲得半數以上票則會進入下一輪投票。此選舉流程與 Paxos 算法相似。
哨兵領導者負責選擇一個slave節點提高爲新 master 節點, 選擇邏輯爲:
slave-priority
配置值最小的從節點。如有多個從節點 slave-priority 最小且相同則進入下一步新的 master 節點選出後會執行提高流程: