redis 系列之——高可用(主從、哨兵、集群)


所謂的高可用,也叫 HA(High Availability),是分布式系統架構設計中必須考慮的因素之一,它通常是指,通過設計減少系統不能提供服務的時間。

 

如果在實際生產中,如果 redis 只部署一個節點,當機器故障時,整改服務都不能提供服務了。這就是我們常說的單點故障。

 

如果 redis 部署了多台,當一台或幾台故障時,整個系統依然可以對外提供服務,這樣就提高了服務的可用性。

 

今天我們就聊聊 redis 高可用的三種模式:主從模式,*哨兵模式*,集群模式。

 

一、主從模式

 

一般,系統的高可用都是通過部署多台機器實現的。redis 為了避免單點故障,也需要部署多台機器。

 

因為部署了多台機器,所以就會涉及到不同機器的的數據同步問題。

 

為此,redis 提供了 Redis 提供了復制(replication)功能,當一台 redis 數據庫中的數據發生了變化,這個變化會被自動的同步到其他的 redis 機器上去。

 

redis 多機器部署時,這些機器節點會被分成兩類,一類是主節點(master 節點),一類是從節點(slave 節點)。一般主節點可以進行讀、寫操作,而從節點只能進行讀操作。同時由於主節點可以寫,數據會發生變化,當主節點的數據發生變化時,會將變化的數據同步給從節點,這樣從節點的數據就可以和主節點的數據保持一致了。一個主節點可以有多個從節點,但是一個從節點會只會有一個主節點,也就是所謂的一主多從結構。

 

 

1.1.機器規划

|機器名稱|IP|端口|

| ---- | ---- | ---- |

| master | 192.168.1.10 | 6379 |

| slave1 | 192.168.1.11 | 6379 |

| slave2 | 192.168.1.12 | 6379 |

| slave3 | 192.168.1.13 | 6379 |

 

1.2.配置

 

主節點配置

 

主節點按照正常的配置配好即可。

 

從節點配置

 

使用默認的配置啟動機器,機器都是主節點。如果想要讓機器變成從節點,需要在 conf 服務器上配置主從復制的相關參數。

 

  • 在從節點的配置文件 redis.conf 中指定主節點的信息(如果需要的話,可以配置主節點的登錄密碼,主從復制相關的參數)。三台從節點的配置是一樣的。

 

 
# 配置主節點的ip和端口slaveof 192.168.1.10 6379# 從redis2.6開始,從節點默認是只讀的slave-read-only yes# 假設主節點有登錄密碼,是123456masterauth 123456
 
 
 
復制代碼
 

 

  • 也可以不配置上面的文件,使用 redis-server 命令,在啟動從節點時,通過參數--slaveof 指定主節點是誰。。

 

 
./redis-server --slaveof 192.168.1.10 6379
 
 
 
復制代碼
 

 

  • 也可以不配上面的文件,正常啟動 redis 機器,然后通過redis-cli的命令行執行slaveof 192.168.1.10 6379指定主節點是誰。

 

系統運行時,如果 master 掛掉了,可以在一個從庫(如 slave1)上手動執行命令slaveof no one,將 slave1 變成新的 master;在 slave2 和 slave3 上分別執行slaveof 192.168.1.11 6379 將這兩個機器的主節點指向的這個新的 master;同時,掛掉的原 master 啟動后作為新的 slave 也指向新的 master 上。

 

執行命令slaveof no one命令,可以關閉從服務器的復制功能。同時原來同步的所得的數據集都不會被丟棄。

 

1.3.機器啟動

 

首先啟動主節點,然后一台一台啟動從節點。

 

1.4.主從復制的機制

 

 

  • 從數據庫連接主數據庫,發送 SYNC 命令;

  • 主數據庫接收到 SYNC 命令后,可以執行 BGSAVE 命令生成 RDB 文件並使用緩沖區記錄此后執行的所有寫命令;

  • 主數據庫 BGSAVE 執行完后,向所有從數據庫發送快照文件,並在發送期間繼續記錄被執行的寫命令;

  • 從數據庫收到快照文件后丟棄所有舊數據,載入收到的快照;

  • 主數據庫快照發送完畢后開始向從數據庫發送緩沖區中的寫命令;

  • 從數據庫完成對快照的載入,開始接受命令請求,並執行來自主數據庫緩沖區的寫命令;(從數據庫初始化完成)

  • 主數據庫每執行一個寫命令就會向從數據庫發送相同的寫命令,從數據庫接收並執行收到的寫命令(從數據庫初始化完成后的操作)

  • 出現斷開重連后,2.8 之后的版本會將斷線期間的命令傳給從數據庫,增量復制。

  • 主從剛剛連接的時候,進行全量同步;全同步結束后,進行增量同步。當然,如果有需要,slave 在任何時候都可以發起全量同步。Redis 的策略是,無論如何,首先會嘗試進行增量同步,如不成功,要求從機進行全量同步。

 

1.5.主從模式的優缺點

 

優點

 

  • 支持主從復制,主機會自動將數據同步到從機,可以進行讀寫分離;

  • 為了分載 Master 的讀操作壓力,Slave 服務器可以為客戶端提供只讀操作的服務,寫服務依然必須由 Master 來完成;

  • Slave 同樣可以接受其他 Slaves 的連接和同步請求,這樣可以有效地分載 Master 的同步壓力;

  • Master 是以非阻塞的方式為 Slaves 提供服務。所以在 Master-Slave 同步期間,客戶端仍然可以提交查詢或修改請求;

  • Slave 同樣是以阻塞的方式完成數據同步。在同步期間,如果有客戶端提交查詢請求,Redis 則返回同步之前的數據。

 

缺點

 

  • Redis 不具備自動容錯和恢復功能,主機從機的宕機都會導致前端部分讀寫請求失敗,需要等待機器重啟或者手動切換前端的 IP 才能恢復;

  • 主機宕機,宕機前有部分數據未能及時同步到從機,切換 IP 后還會引入數據不一致的問題,降低了系統的可用性;

  • 如果多個 Slave 斷線了,需要重啟的時候,盡量不要在同一時間段進行重啟。因為只要 Slave 啟動,就會發送 sync 請求和主機全量同步,當多個 Slave 重啟的時候,可能會導致 Master IO 劇增從而宕機。

  • Redis 較難支持在線擴容,在集群容量達到上限時在線擴容會變得很復雜;

  • redis 的主節點和從節點中的數據是一樣的,降低的內存的可用性

 

二、哨兵模式

 

主從模式下,當主服務器宕機后,需要手動把一台從服務器切換為主服務器,這就需要人工干預,費事費力,還會造成一段時間內服務不可用。這種方式並不推薦,實際生產中,我們優先考慮哨兵模式。這種模式下,master 宕機,哨兵會自動選舉 master 並將其他的 slave 指向新的 master。

 

在主從模式下,redis 同時提供了哨兵命令redis-sentinel,哨兵是一個獨立的進程,作為進程,它會獨立運行。其原理是哨兵進程向所有的 redis 機器發送命令,等待 Redis 服務器響應,從而監控運行的多個 Redis 實例。

 

哨兵可以有多個,一般為了便於決策選舉,使用奇數個哨兵。哨兵可以和 redis 機器部署在一起,也可以部署在其他的機器上。多個哨兵構成一個哨兵集群,哨兵直接也會相互通信,檢查哨兵是否正常運行,同時發現 master 宕機哨兵之間會進行決策選舉新的 master

 

 

哨兵模式的作用:

 

  • 通過發送命令,讓 Redis 服務器返回監控其運行狀態,包括主服務器和從服務器;

  • 當哨兵監測到 master 宕機,會自動將 slave 切換到 master,然后通過發布訂閱模式通過其他的從服務器,修改配置文件,讓它們切換主機;

  • 然而一個哨兵進程對 Redis 服務器進行監控,也可能會出現問題,為此,我們可以使用多個哨兵進行監控。各個哨兵之間還會進行監控,這樣就形成了多哨兵模式。

 

哨兵很像 kafka 集群中的 zookeeper 的功能。

 

2.1.機器規划

 

| 機器名稱 | IP | 端口 |

| ---------- | ------------ | ----- |

| master | 192.168.1.10 | 6379 |

| slave 1 | 192.168.1.11 | 6379 |

| slave 2 | 192.168.1.12 | 6379 |

| slave 3 | 192.168.1.13 | 6379 |

| sentinel 1 | 192.168.1.14 | 26379 |

| sentinel 2 | 192.168.1.15 | 26379 |

| sentinel 3 | 192.168.1.16 | 26379 |

 

這里我們將哨兵進程和 redis 分別部署在不同的機器上,避免因為 redis 宕機導致 sentinel 進程不可用。

 

2.2.配置

 

redis.conf 的配置和上面主從模式一樣,不用變。這里主要說一下哨兵的配置。

 

每台機器的哨兵進程都需要一個哨兵的配置文件sentinel.conf,三台機器的哨兵配置是一樣的。

 

 
# 禁止保護模式protected-mode no# 配置監聽的主服務器,這里sentinel monitor代表監控,mymaster代表服務器的名稱,可以自定義,#192.168.1.10代表監控的主服務器,6379代表端口,2代表只有兩個或兩個以上的哨兵認為主服務器不可用的時候,才會進行failover操作。sentinel monitor mymaster 192.168.1.10 6379 2# sentinel author-pass定義服務的密碼,mymaster是服務名稱,123456是Redis服務器密碼sentinel auth-pass mymaster 123456
 
 
 
復制代碼
 

 

2.3.機器啟動

 

首先啟動主節點,然后一台一台啟動從節點。

 

redis 集群啟動完成后,分別啟動哨兵集群所在機器的三個哨兵,使用redis-sentinel /path/to/sentinel.conf命令。

 

2.4.哨兵模式的工作

 

  • 每個 Sentinel(哨兵)進程以每秒鍾一次的頻率向整個集群中的 Master 主服務器,Slave 從服務器以及其他 Sentinel(哨兵)進程發送一個 PING 命令。

  • 如果一個實例(instance)距離最后一次有效回復 PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 則這個實例會被 Sentinel(哨兵)進程標記為主觀下線(SDOWN)

  • 如果一個 Master 主服務器被標記為主觀下線(SDOWN),則正在監視這個 Master 主服務器的所有 Sentinel(哨兵)進程要以每秒一次的頻率確認 Master 主服務器的確進入了主觀下線狀態

  • 當有足夠數量的 Sentinel(哨兵)進程(大於等於配置文件指定的值)在指定的時間范圍內確認 Master 主服務器進入了主觀下線狀態(SDOWN), 則 Master 主服務器會被標記為客觀下線(ODOWN)

  • 在一般情況下, 每個 Sentinel(哨兵)進程會以每 10 秒一次的頻率向集群中的所有 Master 主服務器、Slave 從服務器發送 INFO 命令。

  • 當 Master 主服務器被 Sentinel(哨兵)進程標記為客觀下線(ODOWN)時,Sentinel(哨兵)進程向下線的 Master 主服務器的所有 Slave 從服務器發送 INFO 命令的頻率會從 10 秒一次改為每秒一次。

  • 若沒有足夠數量的 Sentinel(哨兵)進程同意 Master 主服務器下線, Master 主服務器的客觀下線狀態就會被移除。若 Master 主服務器重新向 Sentinel(哨兵)進程發送 PING 命令返回有效回復,Master 主服務器的主觀下線狀態就會被移除。

 

假設 master 宕機,sentinel 1 先檢測到這個結果,系統並不會馬上進行 failover(故障轉移)選出新的 master,僅僅是QQ賬號地圖主觀的認為 master 不可用,這個現象成為主觀下線。當后面的哨兵也檢測到主服務器不可用,並且數量達到一定值時,那么哨兵之間就會進行一次投票,投票的結果由 sentinel 1 發起,進行 failover 操作。切換成功后,就會通過發布訂閱模式,讓各個哨兵把自己監控的從服務器實現切換主機,這個過程稱為客觀下線。這樣對於客戶端而言,一切都是透明的。

 

2.5.主從模式的優缺點

 

優點

 

  • 哨兵模式是基於主從模式的,所有主從的優點,哨兵模式都具有。

  • 主從可以自動切換,系統更健壯,可用性更高。

 

缺點

 

  • 具有主從模式的缺點,每台機器上的數據是一樣的,內存的可用性較低。

  • Redis 較難支持在線擴容,在集群容量達到上限時在線擴容會變得很復雜。

 

三、集群模式

 

先說一個誤區:Redis 的集群模式本身沒有使用一致性 hash 算法,而是使用 slots 插槽。這是很多人的一個誤區。這里先留個坑,后面我會出一期《 redis 系列之——一致性 hash 算法》。

 

Redis 的哨兵模式基本已經可以實現高可用,讀寫分離 ,但是在這種模式下每台 Redis 服務器都存儲相同的數據,很浪費內存,所以在 redis3.0 上加入了 Cluster 集群模式,實現了 Redis 的分布式存儲,對數據進行分片,也就是說每台 Redis 節點上存儲不同的內容;

 

 

這里的 6 台 redis 兩兩之間並不是獨立的,每個節點都會通過集群總線(cluster bus),與其他的節點進行通信。通訊時使用特殊的端口號,即對外服務端口號加 10000。例如如果某個 node 的端口號是 6379,那么它與其它 nodes 通信的端口號是 16379。nodes 之間的通信采用特殊的二進制協議。

 

對客戶端來說,整個 cluster 被看做是一個整體,客戶端可以連接任意一個 node 進行操作,就像操作單一 Redis 實例一樣,當客戶端操作的 key 沒有分配到該 node 上時,Redis 會返回轉向指令,指向正確的 node,這有點兒像瀏覽器頁面的 302 redirect 跳轉。

 

根據官方推薦,集群部署至少要 3 台以上的 master 節點,最好使用 3 主 3 從六個節點的模式。測試時,也可以在一台機器上部署這六個實例,通過端口區分出來。

 

3.1.機器規划

 

| 機器名稱 | IP | 端口 |

| -------- | ------------ | ---- |

| master 1 | 192.168.1.11 | 6379 |

| master 2 | 192.168.1.12 | 6379 |

| master 3 | 192.168.1.13 | 6379 |

| slave 1 | 192.168.1.21 | 6379 |

| slave 2 | 192.168.1.22 | 6379 |

| slave 3 | 192.168.1.23 | 6379 |

 

3.2.配置

 

修改redis.conf 的配置文件:

 

 
# 開啟redis的集群模式cluster-enabled yes# 配置集群模式下的配置文件名稱和位置,redis-cluster.conf這個文件是集群啟動后自動生成的,不需要手動配置。cluster-config-file redis-cluster.conf
 
 
 
復制代碼
 

 

3.3.機器啟動

 

6 個 Redis 服務分別啟動成功之后,這時雖然配置了集群開啟,但是這六台機器還是獨立的。使用集群管理命令將這 6 台機器添加到一個集群中。

 

借助 redis-tri.rb 工具可以快速的部署集群。

 

只需要執行redis-trib.rb create --replicas 1 192.168.1.11:6379 192.168.1.21:6379 192.168.1.12:6379 192.168.1.22:6379 192.168.1.13:6379 192.168.1.23:6379就可以成功創建集群。

 

該命令執行創建完成后會有響應的日志,通過相關的日志就可以看出集群中機器的關系(不一定和上圖對應),執行的日志如下:

 

 
>>> Performing hash slots allocation on 6 nodes...Master[0] -> Slots 0 - 5460Master[1] -> Slots 5461 - 10922Master[2] -> Slots 10923 - 16383Adding replica 192.168.1.21:6379 to 192.168.1.11:6379Adding replica 192.168.1.22:6379 to 192.168.1.12:6379Adding replica 192.168.1.23:6379 to 192.168.1.13:6379M: 80c80a3f3e33872c047a8328ad579b9bea001ad8 192.168.1.11:6379   slots:[0-5460] (5461 slots) masterS: b4d3eb411a7355d4767c6c23b4df69fa183ef8bc 192.168.1.21:6379   replicates 6788453ee9a8d7f72b1d45a9093838efd0e501f1M: 4d74ec66e898bf09006dac86d4928f9fad81f373 192.168.1.12:6379   slots:[5461-10922] (5462 slots) masterS: b6331cbc986794237c83ed2d5c30777c1551546e 192.168.1.22:6379   replicates 80c80a3f3e33872c047a8328ad579b9bea001ad8M: 6788453ee9a8d7f72b1d45a9093838efd0e501f1 192.168.1.13:6379   slots:[10923-16383] (5461 slots) masterS: 277daeb8660d5273b7c3e05c263f861ed5f17b92 192.168.1.23:6379   replicates 4d74ec66e898bf09006dac86d4928f9fad81f373Can I set the above configuration? (type 'yes' to accept): yes #輸入yes,接受上面配置>>> Nodes configuration updated>>> Assign a different config epoch to each node>>> Sending CLUSTER MEET messages to join the cluster
 
 
 
復制代碼
 

 

執行完成后自動生成配置的 redis-cluster.conf 文件。

 

登錄集群:redis-cli -c -h 192.168.1.11 -p 6379 -a 123456 # -c,使用集群方式登錄

 

查看集群信息:192.168.1.11:6379> CLUSTER INFO #集群狀態

 

列出節點信息:192.168.1.11:6379> CLUSTER NODES #列出節點信息

 

添加數據:

 

 
192.168.1.11:6379> set name aaa-> Redirected to slot [13680] located at 192.168.1.13:6379                #說明最終將數據寫到了192.168.1.13:6379上OK
 
 
 
復制代碼
 

 

獲取數據:

 

 
192.168.1.11:6379> get name-> Redirected to slot [13680] located at 192.168.1.13:6379                #說明最終到192.168.1.13:6379上讀數據"aaa"
 
 
 
復制代碼
 

 

3.4.運行機制

 

在 Redis 的每一個節點上,都有這么兩個東西,一個是插槽(slot),它的的取值范圍是:0-16383,可以從上面redis-trib.rb執行的結果看到這 16383 個 slot 在三個 master 上的分布。還有一個就是 cluster,可以理解為是一個集群管理的插件,類似的哨兵。

 

當我們的存取的 Key 到達的時候,Redis 會根據 crc16 的算法對計算后得出一個結果,然后把結果和 16384 求余數,這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,通過這個值,去找到對應的插槽所對應的節點,然后直接自動跳轉到這個對應的節點上進行存取操作。

 

當數據寫入到對應的 master 節點后,這個數據會同步給這個 master 對應的所有 slave 節點。

 

為了保證高可用,redis-cluster 集群引入了主從模式,一個主節點對應一個或者多個從節點。當其它主節點 ping 主節點 master 1 時,如果半數以上的主節點與 master 1 通信超時,那么認為 master 1 宕機了,就會啟用 master 1 的從節點 slave 1,將 slave 1 變成主節點繼續提供服務。

 

如果 master 1 和它的從節點 slave 1 都宕機了,整個集群就會進入 fail 狀態,因為集群的 slot 映射不完整。如果集群超過半數以上的 master 掛掉,無論是否有 slave,集群都會進入 fail 狀態。

 

redis-cluster 采用去中心化的思想,沒有中心節點的說法,客戶端與 Redis 節點直連,不需要中間代理層,客戶端不需要連接集群所有節點,連接集群中任何一個可用節點即可。

 

3.5.集群擴縮容

 

對 redis 集群的擴容就是向集群中添加機器,縮容就是從集群中刪除機器,並重新將 16383 個 slots 分配到集群中的節點上(數據遷移)。

 

擴縮容也是使用集群管理工具 redis-tri.rb。

 

擴容時,先使用redis-tri.rb add-node將新的機器加到集群中,這是新機器雖然已經在集群中了,但是沒有分配 slots,依然是不起做用的。在使用 redis-tri.rb reshard進行分片重哈希(數據遷移),將舊節點上的 slots 分配到新節點上后,新節點才能起作用。

 

縮容時,先要使用 redis-tri.rb reshard移除的機器上的 slots,然后使用redis-tri.rb add-del移除機器。

 

3.8.集群模式的優缺點

 

優點

 

采用去中心化思想,數據按照 slot 存儲分布在多個節點,節點間數據共享,可動態調整數據分布;

 

可擴展性:可線性擴展到 1000 多個節點,節點可動態添加或刪除;

 

高可用性:部分節點不可用時,集群仍可用。通過增加 Slave 做 standby 數據副本,能夠實現故障自動 failover,節點之間通過 gossip 協議交換狀態信息,用投票機制完成 Slave 到 Master 的角色提升;

 

降低運維成本,提高系統的擴展性和可用性。

 

缺點

 

1.Redis Cluster 是無中心節點的集群架構,依靠 Goss 協議(謠言傳播)協同自動化修復集群的狀態

 

但 GosSIp 有消息延時和消息冗余的問題,在集群節點數量過多的時候,節點之間需要不斷進行 PING/PANG 通訊,不必須要的流量占用了大量的網絡資源。雖然 Reds4.0 對此進行了優化,但這個問題仍然存在。

 

2.數據遷移問題

 

Redis Cluster 可以進行節點的動態擴容縮容,這一過程,在目前實現中,還處於半自動狀態,需要人工介入。在擴縮容的時候,需要進行數據遷移。

 

而 Redis 為了保證遷移的一致性,遷移所有操作都是同步操作,執行遷移時,兩端的 Redis 均會進入時長不等的阻塞狀態,對於小 Key,該時間可以忽略不計,但如果一旦 Key 的內存使用過大,嚴重的時候會接觸發集群內的故障轉移,造成不必要的切換。

 

四、總結

 

主從模式:master 節點掛掉后,需要手動指定新的 master,可用性不高,基本不用。

 

哨兵模式:master 節點掛掉后,哨兵進程會主動選舉新的 master,可用性高,但是每個節點存儲的數據是一樣的,浪費內存空間。數據量不是很多,集群規模不是很大,需要自動容錯容災的時候使用。

 

集群模式:數據量比較大,QPS 要求較高的時候使用。 Redis Cluster 是 Redis 3.0 以后才正式推出,時間較晚,目前能證明在大規模生產環境下成功的案例還不是很多,需要時間檢驗。

 

完成,收工!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM