一、單機模式
單機模式就是只有一個節點提供服務,結構簡單,可靠性低,處理能力弱。這個是最簡單的,一看就懂!

優點:
- 部署簡單;
- 成本低,沒有備用節點,不需要其他的開支;
- 高性能,單機不需要同步數據,數據天然一致性;
缺點:
- 可靠性保證不是很好,單節點有宕機的風險;
- 單機高性能受限於CPU的處理能力,redis是單線程的;
二、主從復制
主從復制,是指將一台Redis服務器的數據,復制到其他的Redis服務器;前者稱為主節點(master),后者稱為從節點(slave);數據的復制是單向的,只能由主節點到從節點。

主從模式配置很簡單,只需要在從節點配置主節點的ip和端口號即可!
slaveof <masterip> <masterport>
# 例如
# slaveof 10.4.7.101 6379
啟動主從節點的所有服務,查看日志即可以看到主從節點之間的服務連接。
從上面很容易就想到一個問題,既然主從復制,意味着master和slave的數據都是一樣的,有數據冗余問題。
在程序設計上,為了高可用性和高性能,是允許有冗余存在的。這點希望大家在設計系統的時候要考慮進去,不用為公司節省這一點資源。
對於追求極致用戶體驗的產品,是絕對不允許有宕機存在的。
主從模式在很多系統設計時都會考慮,一個master掛在多個slave節點,當master服務宕機,會選舉產生一個新的master節點,從而保證服務的高可用性。
優點:
- 一旦主節點宕機,從節點作為主節點的備份可以隨時頂上來;
- 擴展主節點的讀能力,分擔主節點讀壓力;
- 高可用基石,除了上述作用以外,主從復制還是哨兵模式和集群模式能夠實施的基礎,因此說主從復制是Redis高可用的基石;
缺點:
- 一旦主節點宕機,從節點晉升成主節點,同時需要修改應用方的主節點地址,還需要命令所有從節點去復制新的主節點,整個過程需要 人工干預;
- 主節點的寫能力受到單機的限制;
- 主節點的存儲能力受到單機的限制;
三、哨兵模式
剛剛提到了,主從模式,當主節點宕機之后,從節點是可以作為主節點頂上來,繼續提供服務的。
但是有一個問題,主節點的IP已經變動了,此時應用服務還是拿着原主節點的地址去訪問,這...
於是,在Redis 2.8版本開始引入,就有了哨兵這個概念。
在復制的基礎上,哨兵實現了自動化的故障恢復。

如圖,哨兵節點由兩部分組成,哨兵節點和數據節點:
- 哨兵節點:哨兵系統由一個或多個哨兵節點組成,哨兵節點是特殊的redis節點,不存儲數據。
- 數據節點:主節點和從節點都是數據節點。
訪問redis集群的數據都是通過哨兵集群的,哨兵監控整個redis集群。
一旦發現redis集群出現了問題,比如剛剛說的主節點掛了,從節點會頂上來。但是主節點地址變了,這時候應用服務無感知,也不用更改訪問地址,因為哨兵才是和應用服務做交互的。
Sentinel 很好的解決了故障轉移,在高可用方面又上升了一個台階,當然Sentinel還有其他功能。
比如 主節點存活檢測、主從運行情況檢測、主從切換。
Redis的Sentinel最小配置是 一主一從。
原理:
每個Sentinel以每秒鍾一次的頻率,向它所有的主服務器、從服務器 以及其他Sentinel實例發送一個PING 命令。

如果一個 實例(instance)距離最后一次有效回復 PING命令的時間超過 down-after-milliseconds 所指定的值,那么這個實例會被 Sentinel標記為主觀下線。
如果一個主服務器被標記為主觀下線,那么正在監視這個主服務器的所有 Sentinel 節點,要以每秒一次的頻率確認 該主服務器是否的確進入了主觀下線狀態。
如果一個 主服務器 被標記為 主觀下線,並且有足夠數量的 Sentinel(至少要達到配置文件指定的數量)在指定的時間范圍內同意這一判斷,那么這個該主服務器被標記為客觀下線。
在一般情況下, 每個 Sentinel 會以每10秒一次的頻率,向它已知的所有 主服務器 和 從服務器 發送 INFO 命令。
當一個 主服務器 被 Sentinel標記為客觀下線時,Sentinel 向下線主服務器的所有 從服務器 發送 INFO 命令的頻率,會從10秒一次改為每秒一次。
Sentinel和其他 Sentinel 協商主節點的狀態,如果 主節點處於SDOWN狀態,則投票自動選出新的主節點。將剩余的從節點指向新的主節點進行數據復制。
當沒有足夠數量的 Sentinel同意主服務器下線時, 主服務器的客觀下線狀態就會被移除。當主服務器重新向 Sentinel的PING命令返回 有效回復 時,主服務器 的主觀下線狀態就會被移除。
優點:
- 哨兵模式是基於主從模式的,所有主從的優點,哨兵模式都具有;
- 主從可以自動切換,系統更健壯,可用性更高;
- Sentinel 會不斷的檢查 主服務器 和 從服務器 是否正常運行。當被監控的某個 Redis 服務器出現問題,Sentinel 通過API腳本向管理員或者其他的應用程序發送通知;
缺點:
- Redis較難支持在線擴容,對於集群,容量達到上限時在線擴容會變得很復雜;
四、集群模式
主從不能解決故障自動恢復問題,哨兵已經可以解決故障自動恢復了,那到底為啥還要集群模式呢?
主從和哨兵都還有另外一些問題沒有解決,單個節點的存儲能力是有上限,訪問能力是有上限的。
Redis Cluster 集群模式具有 高可用、可擴展性、分布式、容錯 等特性。
原理:
通過數據分片的方式來進行數據共享問題,同時提供數據復制和故障轉移功能。
之前的兩種模式數據都是在一個節點上的,單個節點存儲是存在上限的。集群模式就是把數據進行分片存儲,當一個分片數據達到上限的時候,就分成多個分片。
數據分片怎么分?
集群的鍵空間被分割為16384個slots(即hash槽),通過hash的方式將數據分到不同的分片上的。
HASH_SLOT = CRC16(key) & 16384
CRC16是一種循環校驗算法,這里不是我們研究的重點,有興趣可以看看。
這里用了位運算得到取模結果,位運算的速度高於取模運算。

數據分片之后怎么查,怎么寫?

讀請求分配給slave節點,寫請求分配給master,數據同步從master到slave節點。讀寫分離提高並發能力,增加高性能。
如何做到水平擴展?

master節點可以做擴充,數據遷移redis內部自動完成。
當你新增一個master節點,需要做數據遷移,redis服務不需要下線。
舉個栗子:上面的有三個master節點,意味着redis的槽被分為三個段,假設三段分別是07000,700112000、12001~16383。
現在因為業務需要新增了一個master節點,四個節點共同占有16384個槽。
槽需要重新分配,數據也需要重新遷移,但是服務不需要下線。
redis集群的重新分片由redis內部的管理軟件redis-trib負責執行。redis提供了進行重新分片的所有命令,redis-trib通過向節點發送命令來進行重新分片。
如何做故障轉移?

假如圖中紅色的節點故障了,此時master3下面的從節點會通過 選舉 產生一個主節點。替換原來的故障節點。此過程和哨兵模式的故障轉移是一樣的。
五、總結
每種模式都有各自的優缺點,在實際使用場景中要根據業務特點去選擇合適的模式。
redis是一個非常常用的中間件,作為一個使用者來說,學習成本一點不高。
如果作為一個很好的中間件去研究的話,還是有很多值得學習和借鑒的地方。比如redis的各種數據結構(動態字符串、跳躍表、集合、字典等)、高效的內存分配(jemalloc)、高效的IO模型等等。
每個點都可以深入研究,在后期設計高並發、高可用系統的時候融入進去。
參考博文
