[Redis] 你瞭解 Redis 的三種集羣模式嗎?

最近在面試過程當中被面試官問到 Redis 集羣數據是如何複製的,因爲以前沒有準備直接懵了。

過後查了查這個問題其實也挺簡單,若是你以前也不知道,沒問題,趕忙淺嘗輒止,速度3遍便可入門。html

閱讀本文,你可能會有哪些收穫呢?前端

  • 首先,你會知道有三種集羣模式
  • 而後對每種集羣模式的原理有個大概瞭解
  • 固然還能看到集羣演變的影子
  • 最後還會有手把手的實操

Redis 支持三種集羣方案node

  • 主從複製模式
  • Sentinel(哨兵)模式
  • Cluster 模式

Redis 集羣的三種模式

主從複製模式

img

主從複製的做用

經過持久化功能,Redis保證了即便在服務器重啓的狀況下也不會丟失(或少許丟失)數據,由於持久化會把內存中數據保存到硬盤上,重啓會從硬盤上加載數據。 可是因爲數據是存儲在一臺服務器上的,若是這臺服務器出現硬盤故障等問題,也會致使數據丟失。linux

爲了不單點故障,一般的作法是將數據庫複製多個副本以部署在不一樣的服務器上,這樣即便有一臺服務器出現故障,其餘服務器依然能夠繼續提供服務。nginx

爲此, Redis 提供了複製(replication)功能,能夠實現當一臺數據庫中的數據更新後,自動將更新的數據同步到其餘數據庫上面試

在複製的概念中,數據庫分爲兩類,一類是主數據庫(master),另外一類是從數據庫(slave)。主數據庫能夠進行讀寫操做,當寫操做致使數據變化時會自動將數據同步給從數據庫。而從數據庫通常是隻讀的,並接受主數據庫同步過來的數據。一個主數據庫能夠擁有多個從數據庫,而一個從數據庫只能擁有一個主數據庫。redis

總結:引入主從複製機制的目的有兩個算法

  • 一個是讀寫分離,分擔 "master" 的讀寫壓力
  • 一個是方便作容災恢復

主從複製原理

  • 從數據庫啓動成功後,鏈接主數據庫,發送 SYNC 命令;
  • 主數據庫接收到 SYNC 命令後,開始執行 BGSAVE 命令生成 RDB 文件並使用緩衝區記錄此後執行的全部寫命令;
  • 主數據庫 BGSAVE 執行完後,向全部從數據庫發送快照文件,並在發送期間繼續記錄被執行的寫命令;
  • 從數據庫收到快照文件後丟棄全部舊數據,載入收到的快照;
  • 主數據庫快照發送完畢後開始向從數據庫發送緩衝區中的寫命令;
  • 從數據庫完成對快照的載入,開始接收命令請求,並執行來自主數據庫緩衝區的寫命令;(從數據庫初始化完成
  • 主數據庫每執行一個寫命令就會向從數據庫發送相同的寫命令,從數據庫接收並執行收到的寫命令(從數據庫初始化完成後的操做
  • 出現斷開重連後,2.8以後的版本會將斷線期間的命令傳給重數據庫,增量複製。
  • 主從剛剛鏈接的時候,進行全量同步;全同步結束後,進行增量同步。固然,若是有須要,slave 在任什麼時候候均可以發起全量同步。Redis 的策略是,不管如何,首先會嘗試進行增量同步,如不成功,要求從機進行全量同步。

主從複製優缺點

主從複製優勢shell

  • 支持主從複製,主機會自動將數據同步到從機,能夠進行讀寫分離;
  • 爲了分載 Master 的讀操做壓力,Slave 服務器能夠爲客戶端提供只讀操做的服務,寫服務仍然必須由Master來完成;
  • Slave 一樣能夠接受其它 Slaves 的鏈接和同步請求,這樣能夠有效的分載 Master 的同步壓力;
  • Master Server 是以非阻塞的方式爲 Slaves 提供服務。因此在 Master-Slave 同步期間,客戶端仍然能夠提交查詢或修改請求;
  • Slave Server 一樣是以非阻塞的方式完成數據同步。在同步期間,若是有客戶端提交查詢請求,Redis則返回同步以前的數據;

主從複製缺點數據庫

  • Redis不具有自動容錯和恢復功能,主機從機的宕機都會致使前端部分讀寫請求失敗,須要等待機器重啓或者手動切換前端的IP才能恢復(也就是要人工介入);
  • 主機宕機,宕機前有部分數據未能及時同步到從機,切換IP後還會引入數據不一致的問題,下降了系統的可用性;
  • 若是多個 Slave 斷線了,須要重啓的時候,儘可能不要在同一時間段進行重啓。由於只要 Slave 啓動,就會發送sync 請求和主機全量同步,當多個 Slave 重啓的時候,可能會致使 Master IO 劇增從而宕機。
  • Redis 較難支持在線擴容,在集羣容量達到上限時在線擴容會變得很複雜;

Sentinel(哨兵)模式

第一種主從同步/複製的模式,當主服務器宕機後,須要手動把一臺從服務器切換爲主服務器,這就須要人工干預,費事費力,還會形成一段時間內服務不可用。這不是一種推薦的方式,更多時候,咱們優先考慮哨兵模式。

哨兵模式是一種特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一個獨立的進程,做爲進程,它會獨立運行。其原理是哨兵經過發送命令,等待Redis服務器響應,從而監控運行的多個 Redis 實例

單哨兵

哨兵模式的做用

  • 經過發送命令,讓 Redis 服務器返回監控其運行狀態,包括主服務器和從服務器;
  • 當哨兵監測到 master 宕機,會自動將 slave 切換成 master ,而後經過發佈訂閱模式通知其餘的從服務器,修改配置文件,讓它們切換主機;

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

多哨兵

故障切換的過程

假設主服務器宕機,哨兵1先檢測到這個結果,系統並不會立刻進行 failover 過程,僅僅是哨兵1主觀的認爲主服務器不可用,這個現象成爲主觀下線。當後面的哨兵也檢測到主服務器不可用,而且數量達到必定值時,那麼哨兵之間就會進行一次投票,投票的結果由一個哨兵發起,進行 failover 操做。切換成功後,就會經過發佈訂閱模式,讓各個哨兵把本身監控的從服務器實現切換主機,這個過程稱爲客觀下線。這樣對於客戶端而言,一切都是透明的。

哨兵模式的工做方式:

  • 每一個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主服務器的主觀下線狀態就會被移除。

哨兵模式的優缺點

優勢:

  • 哨兵模式是基於主從模式的,全部主從的優勢,哨兵模式都具備。
  • 主從能夠自動切換,系統更健壯,可用性更高(能夠看做自動版的主從複製)。

缺點:

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

Cluster 集羣模式(Redis官方)

Redis Cluster是一種服務器 Sharding 技術,3.0版本開始正式提供。

Redis 的哨兵模式基本已經能夠實現高可用,讀寫分離 ,可是在這種模式下每臺 Redis 服務器都存儲相同的數據,很浪費內存,因此在 redis3.0上加入了 Cluster 集羣模式,實現了 Redis 的分佈式存儲,也就是說每臺 Redis 節點上存儲不一樣的內容

image-20200531184321294

在這個圖中,每個藍色的圈都表明着一個 redis 的服務器節點。它們任何兩個節點之間都是相互連通的。客戶端能夠與任何一個節點相鏈接,而後就能夠訪問集羣中的任何一個節點。對其進行存取和其餘操做。

集羣的數據分片

Redis 集羣沒有使用一致性 hash,而是引入了哈希槽【hash slot】的概念。

Redis 集羣有16384 個哈希槽,每一個 key 經過 CRC16 校驗後對 16384 取模來決定放置哪一個槽。集羣的每一個節點負責一部分hash槽,舉個例子,好比當前集羣有3個節點,那麼:

  • 節點 A 包含 0 到 5460 號哈希槽
  • 節點 B 包含 5461 到 10922 號哈希槽
  • 節點 C 包含 10923 到 16383 號哈希槽

這種結構很容易添加或者刪除節點。好比若是我想新添加個節點 D , 我須要從節點 A, B, C 中得部分槽到 D 上。若是我想移除節點 A ,須要將 A 中的槽移到 B 和 C 節點上,而後將沒有任何槽的 A 節點從集羣中移除便可。因爲從一個節點將哈希槽移動到另外一個節點並不會中止服務,因此不管添加刪除或者改變某個節點的哈希槽的數量都不會形成集羣不可用的狀態。

在 Redis 的每個節點上,都有這麼兩個東西,一個是插槽(slot),它的的取值範圍是:0-16383。還有一個就是 cluster,能夠理解爲是一個集羣管理的插件。當咱們的存取的 Key到達的時候,Redis 會根據 CRC16 的算法得出一個結果,而後把結果對 16384 求餘數,這樣每一個 key 都會對應一個編號在 0-16383 之間的哈希槽,經過這個值,去找到對應的插槽所對應的節點,而後直接自動跳轉到這個對應的節點上進行存取操做。

Redis 集羣的主從複製模型

爲了保證高可用,redis-cluster集羣引入了主從複製模型,一個主節點對應一個或者多個從節點,當主節點宕機的時候,就會啓用從節點。當其它主節點 ping 一個主節點 A 時,若是半數以上的主節點與 A 通訊超時,那麼認爲主節點 A 宕機了。若是主節點 A 和它的從節點 A1 都宕機了,那麼該集羣就沒法再提供服務了。

集羣的特色

  • 全部的 redis 節點彼此互聯(PING-PONG機制),內部使用二進制協議優化傳輸速度和帶寬。
  • 節點的 fail 是經過集羣中超過半數的節點檢測失效時才生效。
  • 客戶端與 Redis 節點直連,不須要中間代理層.客戶端不須要鏈接集羣全部節點,鏈接集羣中任何一個可用節點便可。

理論課結束了,不如實操下感覺一下?

手把手體驗集羣配置

前提條件

  • 安裝 redis, 我從Redis 官網下載的最新版 redis-5.0.5
  • linux 環境,我用的 centos 7.7, VM 環境
# redis 準備
$ cd /opt
$ wget http://download.redis.io/releases/redis-5.0.5.tar.gz
$ tar xzf redis-5.0.5.tar.gz
$ cd redis-5.0.5
$ make
$ make install

生產環境作集羣通常會採用多個獨立主機,這裏作演示在一臺虛擬機上同時運行多個節點的,這點注意一下。

主從複製

主要有兩步

  • 準備 master/slave 配置文件
  • 先啓動 master 再啓動 slave,進行驗證
集羣規劃
節點 配置文件 端口
master redis6379.conf 6379
slave1 redis6380.conf 6380
slave1 redis6381.conf 6380
配置文件

內容以下

# redis6379.conf    master
# 包含命令,有點複用的意思
include /opt/redis-5.0.5/redis.conf
pidfile /var/run/redis_6379.pid
port    6379
dbfilename dump6379.rdb
logfile "my-redis-6379.log"

# redis6380.conf    slave1
include /opt/redis-5.0.5/redis.conf
pidfile /var/run/redis_6380.pid
port    6380
dbfilename dump6380.rdb
logfile "my-redis-6380.log"
# 最後一行設置了主節點的 ip 端口
replicaof 127.0.0.1 6379

# redis6381.conf    slave2
include /opt/redis-5.0.5/redis.conf
pidfile /var/run/redis_6381.pid
port    6381
dbfilename dump6381.rdb
logfile "my-redis-6381.log"
# 最後一行設置了主節點的 ip 端口
replicaof 127.0.0.1 6379

## 注意 redis.conf 要調整一項,設置後臺運行,對我們操做比較友好
daemonize yes

image-20200531215821358

啓動節點

啓動節點,而後查看節點信息

# 順序啓動節點
$ redis-server redis6379.conf
$ redis-server redis6380.conf
$ redis-server redis6381.conf

# 進入redis 客戶端,開多個窗口查看方便些
$ redis-cli -p 6379
$ info replication

info replication 命令能夠查看鏈接該數據庫的其它庫的信息,可看到有兩個 slave 鏈接到 master

主節點信息

從節點信息

數據同步驗證

在 master 節點設置值,在 slave1/slave2 節點能夠查看數據同步狀況

# master
$ redis-cli -p 6379
127.0.0.1:6379> set k1 v1
OK

# slave1
$ redis-cli -p 6380
127.0.0.1:6380> get k1
"v1"

Sentinel(哨兵)模式

上面也說了哨兵其實主動複製的自動版,因此須要先配置好主從複製,不一樣點在於要增長几個哨兵進行監控。

主要有兩步:

  • 準備主從複製集羣,並啓動
  • 增長哨兵配置,啓動驗證
集羣規劃

通常來講,哨兵模式的集羣是:一主,二從,三哨兵。

那我們就來演示一下三個哨兵的集羣。

節點 配置 端口
master redis6379.conf 6379
slave1 redis6380.conf 6380
slave2 redis6381.conf 6381
sentinel1 sentinel1.conf 26379
sentinel2 sentinel2.conf 26380
sentinel3 sentinel3.conf 26381
哨兵配置

哨兵的配置其實跟 redis.conf 有點像,能夠看一下自帶的 sentinel.conf

這裏我們建立三個哨兵文件, 哨兵文件的區別在於啓動端口不一樣

# 文件內容
# sentinel1.conf
port 26379
sentinel monitor mymaster 127.0.0.1 6379 1
# sentinel2.conf
port 26380
sentinel monitor mymaster 127.0.0.1 6379 1
# sentinel3.conf
port 26381
sentinel monitor mymaster 127.0.0.1 6379 1

image-20200531225859175

啓動哨兵

先把 master-slave 啓動!

而後,挨個把三個都啓動了

$ redis-sentinel sentinel1.conf
$ redis-sentinel sentinel2.conf
$ redis-sentinel sentinel3.conf

啓動以後日誌以下,能夠看到監聽到的主/從節點狀況以及哨兵集羣狀況

image-20200531230243940

主節點下線模擬

咱們在 master(6379) 節點 執行 shutdown,而後觀察哨兵會幫我作什麼?

能夠看到哨兵掃描到了 master 下線, 而後通過一系列判斷,投票等操做從新選舉了master(6381) 節點

image-20200531230641149

能夠查看到,6381 已成爲 master

image-20200531231015090

而後咱們能夠看到, 即便咱們把原 master 節點恢復運行, 它也只是 slave 身份了存在了, 失去了大哥的身份, 可謂是風水輪流轉了

image-20200531231120269

Cluster 集羣模式

Redis 的 Cluster 集羣模式, 啓動還挺簡單

主要有兩步

  • 配置文件
  • 啓動驗證
集羣規劃

根據官方推薦,集羣部署至少要 3 臺以上的master節點,最好使用 3 主 3 從六個節點的模式。

節點 配置 端口
cluster-master1 redis7001.conf 7001
cluster-master2 redis7002.conf 7002
cluster-master3 redis7003.conf 7003
cluster-slave1 redis7004.conf 7004
cluster-slave2 redis7006.conf 7005
cluster-slave3 redis7006.conf 7006
配置文件

我們準備 6 個配置文件 ,端口 7001,7002,7003,7004,7005,7006

分別命名成 redis7001.conf ......redis7006.conf

redis7001.conf 配置文件內容以下(記得複製6份並替換端口號)

# 端口
port 7001  
# 啓用集羣模式
cluster-enabled yes 
# 根據你啓用的節點來命名,最好和端口保持一致,這個是用來保存其餘節點的名稱,狀態等信息的
cluster-config-file nodes_7001.conf 
# 超時時間
cluster-node-timeout 5000
appendonly yes
# 後臺運行
daemonize yes
# 非保護模式
protected-mode no 
pidfile  /var/run/redis_7001.pid
啓動 redis 節點
  • 挨個啓動節點
redis-server redis7001.conf
...
redis-server redis7006.conf

看如下啓動狀況

image-20200601002803562

  • 啓動集羣
# 執行命令
# --cluster-replicas 1 命令的意思是建立master的時候同時建立一個slave

$ redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluste    r-replicas 1
# 執行成功結果以下
# 咱們能夠看到 7001,7002,7003 成爲了 master 節點,
# 分別佔用了 slot [0-5460],[5461-10922],[10923-16383]
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.1:7005 to 127.0.0.1:7001
Adding replica 127.0.0.1:7006 to 127.0.0.1:7002
Adding replica 127.0.0.1:7004 to 127.0.0.1:7003
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 0313641a28e42014a48cdaee47352ce88a2ae083 127.0.0.1:7001
   slots:[0-5460] (5461 slots) master
M: 4ada3ff1b6dbbe57e7ba94fe2a1ab4a22451998e 127.0.0.1:7002
   slots:[5461-10922] (5462 slots) master
M: 719b2f9daefb888f637c5dc4afa2768736241f74 127.0.0.1:7003
   slots:[10923-16383] (5461 slots) master
S: 987b3b816d3d1bb07e6c801c5048b0ed626766d4 127.0.0.1:7004
   replicates 4ada3ff1b6dbbe57e7ba94fe2a1ab4a22451998e
S: a876e977fc2ff9f18765a89c12fbd2c5b5b1f3bf 127.0.0.1:7005
   replicates 719b2f9daefb888f637c5dc4afa2768736241f74
S: ac8d6c4067dec795168ca705bf16efaa5f04095a 127.0.0.1:7006
   replicates 0313641a28e42014a48cdaee47352ce88a2ae083
Can 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
Waiting for the cluster to join
...
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: 0313641a28e42014a48cdaee47352ce88a2ae083 127.0.0.1:7001
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: 4ada3ff1b6dbbe57e7ba94fe2a1ab4a22451998e 127.0.0.1:7002
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: ac8d6c4067dec795168ca705bf16efaa5f04095a 127.0.0.1:7006
   slots: (0 slots) slave
   replicates 0313641a28e42014a48cdaee47352ce88a2ae083
S: a876e977fc2ff9f18765a89c12fbd2c5b5b1f3bf 127.0.0.1:7005
   slots: (0 slots) slave
   replicates 719b2f9daefb888f637c5dc4afa2768736241f74
M: 719b2f9daefb888f637c5dc4afa2768736241f74 127.0.0.1:7003
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 987b3b816d3d1bb07e6c801c5048b0ed626766d4 127.0.0.1:7004
   slots: (0 slots) slave
   replicates 4ada3ff1b6dbbe57e7ba94fe2a1ab4a22451998e
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

image-20200601001049144

數據驗證
# 注意 集羣模式下要帶參數 -c,表示集羣,不然不能正常存取數據!!!
[root@localhost redis-5.0.5]# redis-cli -p 7100 -c
# 設置 k1 v1
127.0.0.1:7001> set k1 v1
-> Redirected to slot [12706] located at 127.0.0.1:7003
OK
# 這能夠看到集羣的特色:把數據存到計算得出的 slot,這裏還自動跳到了 7003
127.0.0.1:7003> get k1
"v1"

# 咱們還回到 7001 獲取 k1 試試
[root@localhost redis-5.0.5]# redis-cli -p 7001 -c
127.0.0.1:7001> get k1
-> Redirected to slot [12706] located at 127.0.0.1:7003
"v1"
# 咱們能夠看到重定向的過程
127.0.0.1:7003>

TODO ?

Docker 版 ?

也許會弄

Reference

B站-尚硅谷周陽老師的視頻課--推薦新手看一看,對實操有幫助

Redis ==> 集羣的三種模式

Redis哨兵(Sentinel)模式

redis cluster集羣模式總結


到這裏關於 Redis 的集羣模式就瞭解的差很少了,完結,撒花 ~

不要只看不敲哦,只看或者只收藏不敲等於耍流氓 !

相關文章
相關標籤/搜索