Redis 模式
我們項目接觸redis一開始是作為緩存,主要是因為它的速度快。其次是用於分布式鎖,如果有興趣還可以用來做布隆過濾器。
redis的模式基本分4種,在實際 生產環境中,主要還是集群
。
討論的redis版本,以4.0為主。
單點 Standalone
這基本不用說,官網上面的demo就有,自己的網站部署玩一玩可以。
優點是不用花什么錢,自己的雲服務器上面就可以安裝一個。
缺點是 很明顯,一台redis掛了,其他依賴redis的服務也就掛了。
主從 Master/Slave
結構圖:
一個Master,可以有多個Slave,Slave 也可以有自己的Slave。這樣簡單的主從結構就完成了。
Master一般是用來做write,Slave一般是用來read。這樣的結構可以有效的緩解系統的讀寫壓力。
因為Master是負責write,那么就會出現主從數據的不同步,就需要通過sync,把Master的數據同步給Slave。【rdb文件,backlog】
具體點就會區分:
- 全量復制:slave剛接入,需要把master上的數據全部同步
- 增量復制:slave,網絡中斷,超時,導致部分數據需要增量同步
但是問題也隨之而來,如果Master掛了,怎么辦? 需要手動去調整
如果要恢復有2種方式
-
新增一台機器做Maste
-
將其中一台Slave,轉成Master
也就意味着短時間內無法寫入數據,雖然可以讀取。從高可用性來說,這個結構是不完善的,因為功能已經不全了。在恢復的過程中,肯定會有部分的業務會受到影響,對於某些HA高的業務自然不能忍受。
哨兵 Sentinel
sentinel可以算是Master/Slave的改進。
在當Master無法正常工作時,Slave無法自己選出一個Master,就需要sentinel來做這個事。但是問題來了,如果sentinel也掛了,怎么辦?
所以這個結構的優缺點就很明顯了
-
優點: 快速響應自動故障切換,無需人工介入,客戶端無需感知redis狀態。
支持HA,可以滿足一般的生產需求。
-
缺點: 需要維護sentinel的信息,而且水平擴展會很難處理。
集群 Cluster
對於cluster來說,基本特點就是高可用,可擴展,負載均衡。
圖片實在懶得畫了,找了一個比較好理解的
Redis 集群是一個提供在多個Redis間節點間共享數據的程序集。
Redis集群並不支持處理多個keys的命令,因為這需要在不同的節點間移動數據,從而達不到像Redis那樣的性能,在高負載的情況下可能會導致不可預料的錯誤.
Redis 集群通過分區來提供一定程度的可用性,在實際環境中當某個節點宕機或者不可達的情況下繼續處理命令. Redis 集群的優勢:
- 自動分割數據到不同的節點上。
- 整個集群的部分節點失敗或者不可達的情況下能夠繼續處理命令。
Redis 集群的數據分片
Redis 集群沒有使用一致性hash, 而是引入了 哈希槽的概念.
Redis 集群有16384個哈希槽,每個key通過CRC16校驗后對16384取模來決定放置哪個槽.集群的每個節點負責一部分hash槽,舉個例子,比如當前集群有3個節點,那么:
- 節點 A 包含 0 到 5500號哈希槽.
- 節點 B 包含5501 到 11000 號哈希槽.
- 節點 C 包含11001 到 16384號哈希槽.
這種結構很容易添加或者刪除節點. 比如如果我想新添加個節點D, 我需要從節點 A, B, C中得部分槽到D上. 如果我想移除節點A,需要將A中的槽移到B和C節點上,然后將沒有任何槽的A節點從集群中移除即可. 由於從一個節點將哈希槽移動到另一個節點並不會停止服務,所以無論添加刪除或者改變某個節點的哈希槽的數量都不會造成集群不可用的狀態.
Redis 集群的主從復制模型
為了使在部分節點失敗或者大部分節點無法通信的情況下集群仍然可用,所以集群使用了主從復制模型,每個節點都會有N-1個復制品.
在我們例子中具有A,B,C三個節點的集群,在沒有復制模型的情況下,如果節點B失敗了,那么整個集群就會以為缺少5501-11000這個范圍的槽而不可用.
然而如果在集群創建的時候(或者過一段時間)我們為每個節點添加一個從節點A1,B1,C1,那么整個集群便有三個master節點和三個slave節點組成,這樣在節點B失敗后,集群便會選舉B1為新的主節點繼續服務,整個集群便不會因為槽找不到而不可用了
不過當B和B1 都失敗后,集群是不可用的.
Redis 一致性保證
Redis 並不能保證數據的強一致性. 這意味這在實際中集群在特定的條件下可能會丟失寫操作.
第一個原因是因為集群是用了異步復制. 寫操作過程:
- 客戶端向主節點B寫入一條命令.
- 主節點B向客戶端回復命令狀態.
- 主節點將寫操作復制給他得從節點 B1, B2 和 B3.
主節點對命令的復制工作發生在返回命令回復之后, 因為如果每次處理命令請求都需要等待復制操作完成的話, 那么主節點處理命令請求的速度將極大地降低 —— 我們必須在性能和一致性之間做出權衡。 注意:Redis 集群可能會在將來提供同步寫的方法。 Redis 集群另外一種可能會丟失命令的情況是集群出現了網絡分區, 並且一個客戶端與至少包括一個主節點在內的少數實例被孤立。
舉個例子 假設集群包含 A 、 B 、 C 、 A1 、 B1 、 C1 六個節點, 其中 A 、B 、C 為主節點, A1 、B1 、C1 為A,B,C的從節點, 還有一個客戶端 Z1 假設集群中發生網絡分區,那么集群可能會分為兩方,大部分的一方包含節點 A 、C 、A1 、B1 和 C1 ,小部分的一方則包含節點 B 和客戶端 Z1 .
Z1仍然能夠向主節點B中寫入, 如果網絡分區發生時間較短,那么集群將會繼續正常運作,如果分區的時間足夠讓大部分的一方將B1選舉為新的master,那么Z1寫入B中得數據便丟失了.
注意, 在網絡分裂出現期間, 客戶端 Z1 可以向主節點 B 發送寫命令的最大時間是有限制的, 這一時間限制稱為節點超時時間(node timeout), 是 Redis 集群的一個重要的配置選項。
內容引用: