1. 程式人生 > >redis 叢集詳解及搭建過程

redis 叢集詳解及搭建過程

1. 引言

從 3.0 版本開始,redis 具備了叢集功能,實現了分散式、容錯、去中心化等特性,在生產環境中對於保證資料一致性和安全性、提高系統響應能力都有著很必要的意義。
本文我們就來介紹 redis 叢集的三種搭建模式和搭建方法。

1.1. redis 叢集的特性

redis 叢集的目標是線性可擴充套件性和保證最終一致性,因此,redis 叢集不存在中心節點或代理節點。
同時,一致性的保證是建立在一部分容錯性犧牲的基礎上的,系統通過主從節點的模式在保證對節點失效具有有限抵抗力的前提下,儘可能保證資料的一致性。
redis 叢集實現了節點的自動發現、master 的自動選舉、熱分片、ASK 轉向和 MOVED 轉向等機制。
可以參考官方文件:

https://redis.io/topics/cluster-tutorial。

1.2. 叢集埠

無論是哪種模式的 redis 叢集,都需要指定服務埠(預設為 6379),但 redis 實際上是通過服務埠 + 10000 的埠來進行資料同步的。
因此,如果叢集無法建立或同步無法進行,除了需要考慮服務埠是否連通以外,還需要檢測同步埠的可用性。

2. 主從模式叢集

# 此處有圖片

redis 支援簡單的主從單向同步的叢集結構,主節點負責寫入資料,同步到從節點,從節點進行只讀操作。
主從單向同步的叢集結構可以有效提升系統的吞吐量,同時保證資料的安全性。

2.1. 搭建方法

主從模式的叢集搭建方法非常簡單,只需要在從節點的配置檔案中寫入:

slaveof 112.126.74.142 6379

這樣,啟動該節點後,他就成為了 112.126.74.142:6379 節點的從節點。

2.2. 從節點的寫入操作

需要注意的是,從節點預設也可以進行讀寫操作,但從節點的寫入將會導致這部分資料不會被同步,從而造成資料不一致的問題。
可以通過指定配置來強制從節點不可寫入:

replica-read-only yes

此時對從節點進行寫入操作會報錯:

(error) READONLY You can't write against a read only replica.

2.3. 從節點的同步機制

在 redis-cli 中,通過執行 info replication 可以看到叢集資訊。

# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:6
master_sync_in_progress:0
slave_repl_offset:462
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:201640b5a63c036087b7a459245a6f6a699b8a36
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:462
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:462

其中有兩個標識:

  1. master_replid – 長度為41個位元組的字串,主節點標識
  2. master_replid2 – 該節點上一次連線主例項的例項 master_replid
    如果 A 是叢集主節點,B 是 A 的從節點,C 是 B 的從節點,那麼 C 的 master_replid 則儲存的是 A 的節點標識,這意味著,如果 B 節點非只讀,B 節點內寫入的資料並不會同步到 C 節點。
    資料的同步就是基於 master_replid 與 master_repl_offset 兩個欄位進行的,每個從節點都儲存了當前已同步資料的偏移,從而實現部分同步。
    主節點一旦重啟,master_replid 就會發生變動,從而造成所有從節點重新同步全量資料,由於 master_replid 是自動生成的,我們並不能干涉這一過程。

3. 高可用叢集 – HA

上面所描述的主從叢集存在一個問題,那就是當主節點宕機時,將導致整個叢集無法提供服務。
為了保證叢集的容錯性,redis 提供了官方的 HA 方案,他是通過建立哨兵節點或哨兵叢集來實現對 master 的監控和對 slaver 的提權。
哨兵節點通過監控 redis 叢集中 master 的狀態實現當 master 狀態異常時,在 master 的多個 slaver 中選舉一個並通過傳送 SLAVEOF NO ONE 命令提升其為 master 節點,同時自動傳送 SLAVE OF 命令給其他 slaver 節點,從而讓叢集重新工作起來,這個過程稱為 failover 過程。
多個哨兵節點可以組成叢集,從而避免某個哨兵節點宕機的情況發生。

# 此處有圖片

3.1. 叢集搭建

首先,我們需要建立哨兵節點配置檔案:

port 20086      #預設埠26379
dir "/tmp"
logfile "/var/log/redis/sentinel_20086.log"
daemonize yes

# 配置監視的進群的主節點 ip 和埠 1 表示至少需要幾個哨兵統一認定才可以做出判斷
sentinel monitor mymaster 127.0.0.1 6380 1

# 表示如果 5s 內 mymaster 沒響應,就認為 SDOWN 
sentinel down-after-milliseconds mymaster 5000 

# 表示如果15秒後,mysater 仍沒活過來,則啟動 failover,從剩下從節點序曲新的主節點
sentinel failover-timeout mymaster 15000 

# 在發生failover主備切換時,這個選項指定了最多可以有多少個slave同時對新的master進行同步,這個數字越小,完成failover所需的時間就越長,但是如果這個數字越大,就意味著越多的slave因為replication而不可用。可以通過將這個值設為 1 來保證每次只有一個slave處於不能處理命令請求的狀態
sentinel parallel-syncs T1 1

# sentinel 連線設定了密碼和主從
# sentinel auth-pass <master_name> xxxxx

# 發生切換之後執行的一個自定義指令碼
# sentinel client-reconfig-script <master-name> <script-path>

通過 redis-sentinel 命令指定配置檔案啟動即可。

4. redis-cluster

儘管可以使用哨兵主從叢集實現可用性保證,但是這種實現方式每個節點的資料都是全量複製,資料存放量存在著侷限性,受限於記憶體最小的節點。
為了增大儲存效能,實現真正的分散式儲存系統,sharding 的方案是非常有必要的。
所謂的 sharding 方案指的是將全量資料分成 16384 個雜湊槽,我們只需採用金鑰模數 16384 的 CRC16 就可以計算 key 所在的雜湊槽位置,這樣,每個節點容納全部 16384 個雜湊槽中的一部分,所有 master 節點共同組成完整的資料。

# 此處有圖片

4.1. 配置叢集

如果需要 sharding 模式與主從模式結合使用,那麼需要在建立叢集時通過命令指定,而不能在配置檔案中新增 slaveof 配置項。
首先修改 redis 配置開啟 cluster 配置:

################################ REDIS CLUSTER  ###############################
#
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# WARNING EXPERIMENTAL: Redis Cluster is considered to be stable code, however
# in order to mark it as "mature" we need to wait for a non trivial percentage
# of users to deploy it in production.
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#
# Normal Redis instances can't be part of a Redis Cluster; only nodes that are
# started as cluster nodes can. In order to start a Redis instance as a
# cluster node enable the cluster support uncommenting the following:
#
cluster-enabled yes

# Every cluster node has a cluster configuration file. This file is not
# intended to be edited by hand. It is created and updated by Redis nodes.
# Every Redis Cluster node requires a different cluster configuration file.
# Make sure that instances running in the same system do not have
# overlapping cluster configuration file names.
#
cluster-config-file /etc/redis/nodes-6379.conf

# Cluster node timeout is the amount of milliseconds a node must be unreachable
# for it to be considered in failure state.
# Most other internal time limits are multiple of the node timeout.
#
cluster-node-timeout 15000

cluster-config-file 配置的檔案 redis 叢集啟動後會自動寫入叢集資訊,如果要刪除叢集重建,最暴力的方法就是刪除叢集中每臺機器上的 cluster-config-file 配置檔案。

其他配置項還有:

  • cluster-slave-validity-factor – slave節點與master斷線的時間是否過長,如果 (node-timeout * slave-validity-factor) + repl-ping-slave-period 大於了該值,則 slave 不會被提升為 master,預設值為 10
  • cluster-migration-barrier – master 的最小 slaver 數,避免組建叢集時 slaver 不能平均分配的情況發生,預設為 0
  • cluster-require-full-coverage – 是否 sharding 所有 slot 才能夠提供服務,預設為 yes,如果設定為 no,可以在 slot 沒有全部分配的時候提供服務,不建議,這樣會造成分割槽的時候,小分割槽的master一直在接受寫請求,而造成很長時間資料不一致

4.2. 啟動叢集

首先,更新完配置後,需要啟動所有節點的 redis-server。
redis5.0 版本以後叢集操作從 redis-trib.rb 命令遷移到 redis-cli,通過 redis-cli --cluster 命令就可以組建叢集了。

redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 --cluster-replicas 1

–cluster-replicas 指定了叢集中每個 master 節點的 slaver 數量。

# 此處有圖片

  • 需要注意的是,至少三臺 master 主機才能組成一個 redis-cluster,並且叢集中的所有節點初始時必須不能有資料

4.3. 報錯處理 – Not all 16384 slots are covered by nodes

# 此處有圖片

可以通過 redis-cli --cluster fix 命令修復,讓叢集中槽位重新分佈。
通過執行 redis-cli --cluster check host:port 可以檢測叢集中的槽位分佈情況。
官方文件中還介紹了叢集的其他操作,例如節點的新增和刪除,可以進一步閱讀。

4.4. MOVED xxx xxx.xxx.xxx.xxx:xxxx

使用 redis-cli 連線叢集進行操作,會出現 MOVED 錯誤。

# 此處有圖片

這是因為出現了 MOVED 轉向,提示客戶端轉向分片所在節點進行操作,關於 MOVED 轉向和 ASK 轉向我們下一篇文章中再來介紹。
redis 要求客戶端自己處理 MOVED 轉向和 ASK 轉向,所以 redis-cli 中已經擁有了處理邏輯,只需在登入時增加 -c 引數即可自動進行轉向,也就不會再報出相應的錯誤了。
在這裡插入圖片描述

5. 參考資料

https://redis.io/topics/cluster-tutorial。
https://blog.csdn.net/qq_20597727/article/details/83385737。
https://www.cnblogs.com/vansky/p/9130647.html。
https://www.cnblogs.com/zhoujinyi/p/5570024.html。
https://blog.csdn.net/vtopqx/article/details/50235737。
https://blog.csdn.net/huwei2003/article/details/50973893。