一、Redis叢集概述
1)Redis 主從複制
到 目前 為止,我們所學習的 Redis 都是 單機版 的,這也就意味着一旦我們所依賴的 Redis 服務當機了,我們的主流程也會受到一定的影響,這當然是我們不能夠接受的。
是以一開始我們的想法是:搞一台備用機。這樣我們就可以在一台伺服器出現問題的時候切換動态地到另一台去:

幸運的是,兩個節點資料的同步我們可以使用 Redis 的 主從同步 功能幫助到我們,這樣一來,有個備份,心裡就踏實多了。
2)Redis 哨兵
後來因為某種神秘力量,Redis 老會在莫名其妙的時間點出問題 (比如半夜 2 點),我總不能 24 小時時刻守在電腦旁邊切換節點吧,于是另一個想法又開始了:給所有的節點找一個 "管家",自動幫我監聽照顧節點的狀态并切換:
這大概就是 Redis 哨兵 (Sentinel) 的簡單了解啦。什麼?管家當機了怎麼辦?相較于有大量請求的 Redis 服務來說,管家當機的機率就要小得多啦.. 如果真的當機了,我們也可以直接切換成目前可用的節點保證可用..
3)Redis 叢集化
好了,通過上面的一些解決方案我們對 Redis 的 穩定性 稍微有了一些底氣了,但單台節點的計算能力始終有限,所謂人多力量大,如果我們把 多個節點組合 成 一個可用的工作節點,那就大大增加了 Redis 的 高可用、可擴充、分布式、容錯 等特性:
二、主從複制
主從複制,是指将一台 Redis 伺服器的資料,複制到其他的Redis伺服器。前者稱為 主節點 (master/leader),後者稱為 從節點(slave/follower) ;資料的複制是單向的,隻能由主節點到從節點。 Master以寫為主,Slave 以讀為主。 預設情況下,每台Redis伺服器都是主節點; 且一個主節點可以有多個從節點(或沒有從節點),但一個從節點隻能有一個主節點
主從複制主要的作用
- 資料備援: 主從複制實作了資料的熱備份,是持久化之外的一種資料備援方式。
- 故障恢複: 當主節點出現問題時,可以由從節點提供服務,實作快速的故障恢複 (實際上是一種服務的備援)。
- 負載均衡: 在主從複制的基礎上,配合讀寫分離,可以由主節點提供寫服務,由從節點提供讀服務 (即寫 Redis 資料時應用連接配接主節點,讀 Redis 資料時應用連接配接從節點),分擔伺服器負載。尤其是在寫少讀多的場景下,通過多個從節點分擔讀負載,可以大大提高 Redis 伺服器的并發量。
- 高可用基石: 除了上述作用以外,主從複制還是哨兵和叢集能夠實施的 基礎,是以說主從複制是 Redis 高可用的基礎。
一般來說,要将 Redis 運用于工程項目中,隻使用一台 Redis 是萬萬不能的(當機),原因如下:
1、從結構上,單個 Redis 伺服器會發生單點故障,并且一台伺服器需要處理所有的請求負載,壓力較大;
2、從容量上,單個 Redis 伺服器記憶體容量有限,就算一台 Redis 伺服器記憶體容量為 256G,也不能将所有 記憶體用作 Redis 存儲記憶體,一般來說,單台 Redis 最大使用記憶體不應該超過 20G。
比如:電商網站上的商品,一般都是一次上傳,無數次浏覽的,也就是"多讀少寫"。
對于這種場景,我們可以使用這種架構:主從複制,讀寫分離。一個網站 80% 的情況下都是在進行讀操作,為了減緩伺服器的壓力,一般都會配置多态伺服器(一主二從)。 隻要在公司中,主從複制就是必須要使用的,因為在真實的項目中不可能單機使用 Redis。
1)快速體驗(這裡條件不允許,就是用單機多服務進行測試)
① 環境配置
隻配置從庫,不用配置主庫!
127.0.0.1:6379> info replication # 檢視目前庫的資訊
# Replication
role:master # 角色 master
connected_slaves:0 # 沒有從機
master_replid:b63c90e6c501143759cb0e7f450bd1eb0c70882a
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
複制3個配置檔案,然後修改對應的資訊:
- 端口
- pid 名字
- log 檔案名字
- dump.rdb 名字
啟動我們的3個redis伺服器:
② 建立複制
我們在 6380、6381 端口的節點中執行 slaveof 指令,使之變為從節點:
# 成為本地 6379 端口執行個體的從節點
127.0.0.1:6380> SLAVEOF 127.0.0.1 6379
OK
如果兩個都配置完了,就是有兩個從機的
真實的從主配置應該在配置檔案中配置,這樣的話是永久的,我們這裡使用的是指令,暫時的!
③ 效果測試
主機可以寫,從機不能寫隻能讀。主機中的所有資訊和資料,都會自動被從機儲存!
主機寫:
從機隻能讀取内容!
測試:主機斷開連接配接,從機依舊連接配接到主機的,但是沒有寫操作,這個時候,主機如果回來了,從機依 舊可以直接擷取到主機寫的資訊!
如果是使用指令行,來配置的主從,這個時候如果重新開機了,就會變回主機!隻要變為從機,立馬就會從 主機中擷取值!
2)複制原理
Slave 啟動成功連接配接到 master 後會發送一個 sync 同步指令
Master 接到指令,啟動背景的存盤程序,同時收集所有接收到的用于修改資料集指令,在背景程序執行 完畢之後,master 将傳送整個資料檔案到 slave,并完成一次完全同步。
全量複制:而 slave 服務在接收到資料庫檔案資料後,将其存盤并加載到記憶體中。
增量複制:Master 繼續将新的所有收集到的修改指令依次傳給 slave,完成同步
但是隻要是重新連接配接 master,一次完全同步(全量複制)将被自動執行! 我們的資料一定可以在從機中 看到!
3)層層鍊路
上一個M連結下一個 S!
這時候也可以完成我們的主從複制!
4)主機挂了怎麼辦?
如果主機斷開了連接配接,我們可以使用 SLAVEOF no one 讓自己變成主機!其他的節點就可以手動連 接到最新的這個主節點(手動)!如果這個時候老大修複了,那就重新連接配接!
很明顯這是一個愚蠢的方法。當主伺服器當機後,需要手動把一台從伺服器切換為主伺服器,這就需要人工 幹預,費事費力,還會造成一段時間内服務不可用。這不是一種推薦的方式,更多時候,我們優先考慮 哨兵模式。Redis 從2.8開始正式提供了 Sentinel(哨兵) 架構來解決這個問題。
是以下面我們要學習哨兵模式(自動選舉老大的模式)
三、哨兵模式
哨兵模式是一種特殊的模式,首先 Redis 提供了哨兵的指令,哨兵是一個獨立的程序,作為程序,它會獨 立運作。其原理是 哨兵通過發送指令,等待 Redis 伺服器響應,進而監控運作的多個 Redis 執行個體。
這裡的哨兵有兩個作用
- 通過發送指令,讓 Redis 伺服器傳回監控其運作狀态,包括主伺服器和從伺服器。
- 當哨兵監測到 master 當機,會自動将 slave 切換成 master ,然後通過釋出訂閱模式通知其他的從服 務器,修改配置檔案,讓它們切換主機
然而一個哨兵程序對 Redis 伺服器進行監控,可能會出現問題,為此,我們可以使用多個哨兵進行監控。 各個哨兵之間還會進行監控,這樣就形成了多哨兵模式。
假設主伺服器當機,哨兵 1 先檢測到這個結果,系統并不會馬上進行failover過程,僅僅是哨兵1主觀的認 為主伺服器不可用,這個現象成為 主觀下線。當後面的哨兵也檢測到主伺服器不可用,并且數量達到一 定值時,那麼哨兵之間就會進行一次投票,投票的結果由一個哨兵發起,進行 failover [故障轉移]操作。 切換成功後,就會通過釋出訂閱模式,讓各個哨兵把自己監控的從伺服器實作切換主機,這個過程稱為 客觀下線。
1)快速體驗
① 建立主從節點配置檔案并啟動
複制三份 redis.conf 配置檔案分别命名為 redis-6379.conf、redis-6380.conf、redis-6381.conf 分别作為
1
個主節點和
2
個從節點的配置檔案。
打開 .conf 配置檔案,分别添加修改以下配置:
#主機:redis-6379.conf
port 6379
bind 0.0.0.0
pidfile /var/run/redis_6379.pid
logfile "6379.log"
dbfilename "dump-6379.rdb"
#從機:redis-6380.conf
port 6380
bind 0.0.0.0
pidfile /var/run/redis_6380.pid
logfile "6380.log"
dbfilename "dump-6380.rdb"
slaveof 127.0.0.1 6379 # 配置主機
#從機:redis-6381.conf
port 6381
bind 0.0.0.0
pidfile /var/run/redis_6381.pid
logfile "6381.log"
dbfilename "dump-6381.rdb"
slaveof 127.0.0.1 6379 # 配置主機
然後我們可以執行 redis-server <config file path> 來根據配置檔案啟動不同的 Redis 執行個體,依次啟動主從節點:
redis-server myconf/redis-6379.conf
redis-server myconf/redis-6380.conf
redis-server myconf/redis-6381.conf
節點啟動後,我們執行 redis-cli 預設連接配接到我們端口為 6379 的主節點執行 info replication 檢查一下主從狀态是否正常:
Redis - 叢集
② 建立哨兵節點配置檔案并啟動
按照上面同樣的方法,我們給哨兵節點也建立三個配置檔案。(哨兵節點本質上是特殊的 Redis 節點,是以配置幾乎沒什麼差别,隻是在端口上做區分就好)
# redis-sentinel-1.conf
port 26379 # 哨兵端口
daemonize yes # 以背景運作
logfile "26379.log" # 日志檔案
# sentinel monitor 被監控的名稱 host port 1
sentinel monitor myredis 127.0.0.1 6379 1
# redis-sentinel-2.conf
port 26380
daemonize yes
logfile "26380.log"
sentinel monitor myredis 127.0.0.1 6379 1
# redis-sentinel-3.conf
port 26381
daemonize yes
logfile "26381.log"
sentinel monitor myredis 127.0.0.1 6379 1
後面的這個數字 1,代表主機挂了,slave 投票看讓誰接替成為主機,票數最多的,就會成為主機!
執行下方指令将哨兵節點啟動起來:
redis-sentinel myconfig/redis-sentinel-1.conf
redis-sentinel myconfig/redis-sentinel-2.conf
redis-sentinel myconfig/redis-sentinel-3.conf
使用 redis-cli 工具連接配接哨兵節點,并執行 info Sentinel指令來檢視是否已經在監視主節點了:
# 連接配接端口為 26379 的 Redis 節點
[root@cyan bin]# redis-cli -p 26379
127.0.0.1:26379> info Sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3
此時你打開剛才寫好的哨兵配置檔案,你還會發現出現了一些變化
③ 示範故障轉移
首先,我們使用 kill -s 9 指令來殺掉主節點,同時 在哨兵節點中執行 info Sentinel 指令來觀察故障節點的過程:
# 檢視redis服務
[root@cyan ~]# ps -aux|grep redis
root 17438 0.1 0.1 169352 3444 ? Ssl 15:10 0:05 redis-server *:6379
root 17443 0.1 0.1 159624 3076 ? Ssl 15:10 0:04 redis-server *:6380
root 17450 0.1 0.1 159624 3084 ? Ssl 15:10 0:04 redis-server *:6381
root 17454 0.0 0.0 24856 1580 pts/0 S+ 15:10 0:00 redis-cli -p 6379
root 17455 0.0 0.0 24856 1576 pts/2 S+ 15:10 0:00 redis-cli -p 6380
root 17456 0.0 0.0 24856 1584 pts/3 S+ 15:11 0:00 redis-cli -p 6381
root 26699 0.2 0.1 153992 2648 ? Ssl 16:06 0:02 redis-sentinel *:26379 [sentinel]
root 26707 0.2 0.1 153992 2648 ? Ssl 16:06 0:02 redis-sentinel *:26380 [sentinel]
root 26713 0.2 0.1 153992 2640 ? Ssl 16:06 0:02 redis-sentinel *:26381 [sentinel]
root 26867 0.0 0.0 112812 972 pts/4 R+ 16:23 0:00 grep --color=auto redis
root 31944 0.0 0.0 24724 1388 pts/1 S+ 16:09 0:00 redis-cli -p 26379
# kill Redis服務
[root@cyan ~]# kill -s 9 17438
如果 剛殺掉瞬間 在哨兵節點中執行 info 指令來檢視,會發現主節點還沒有切換過來,因為哨兵發現主節點故障并轉移需要一段時間:
# 第一時間檢視哨兵節點發現并未轉移,還在 6379 端口
127.0.0.1:26379> INFO sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=odown,address=127.0.0.1:6379,slaves=2,sentinels=3
一段時間之後你再執行 info 指令,檢視,你就會發現主節點已經切換成了 6381 端口的從節點:
# 過一段時間之後在執行,發現已經切換了 6381 端口
127.0.0.1:26379> info Sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6381,slaves=2,sentinels=3
但同時還可以發現,哨兵節點認為新的主節點仍然有兩個從節點 (上方 slaves=2),這是因為哨兵在将 6381 切換成主節點的同時,将 6379 節點置為其從節點。雖然 6379 從節點已經挂掉,但是由于 哨兵并不會對從節點進行客觀下線,是以認為該從節點一直存在。當 6379 節點重新啟動後,會自動變成 6381 節點的從節點。
另外,在故障轉移的階段,哨兵和主從節點的配置檔案都會被改寫:
● 對于主從節點: 主要是 slaveof 配置的變化,新的主節點沒有了 slaveof 配置,其從節點則 slaveof 新的主節點。
● 對于哨兵節點:除了主從節點資訊的變化,紀元(epoch)(記錄目前叢集狀态的參數)也會變化,紀元相關的參數都 +1 了。
2)新的主機是怎麼選舉出來的
故障轉移操作的第一步 要做的就是在已下線主伺服器屬下的所有從伺服器中,挑選出一個狀态良好、資料完整的從伺服器,然後向這個從伺服器發送 slaveof no one 指令,将這個從伺服器轉換為主伺服器。但是這個從伺服器是怎麼樣被挑選出來的呢?
簡單來說 Sentinel 使用以下規則來選擇新的主伺服器:
① 在失效主伺服器屬下的從伺服器當中, 那些被标記為主觀下線、已斷線、或者最後一次回複 PING 指令的時間大于五秒鐘的從伺服器都會被 淘汰。
② 在失效主伺服器屬下的從伺服器當中, 那些與失效主伺服器連接配接斷開的時長超過 down-after 選項指定的時長十倍的從伺服器都會被淘汰。
③ 在經曆了以上兩輪淘汰之後剩下來的從伺服器中, 我們選出複制偏移量(replication offset)最大的那個從伺服器作為新的主伺服器;如果複制偏移量不可用,或者從伺服器的複制偏移量相同,那麼帶有最小運作 ID的那個從伺服器成為新的主伺服器。
3)哨兵的優缺點
● 優點:
1、哨兵叢集,基于主從複制模式,所有的主從配置優點,它全有
2、主從可以切換,故障可以轉移,系統的可用性就會更好
3、哨兵模式就是主從模式的更新,手動到自動,更加健壯!
● 缺點:
1、Redis 不好線上擴容,叢集容量一旦到達上限,線上擴容就十分麻煩!
2、實作哨兵模式的配置其實是很麻煩的,裡面有很多選擇!
@ 非原創 - @ 作者:我沒有三顆心髒