一文讀懂Redis的四種模式,單機、主從、哨兵、叢集

龍躍十二發表於2020-06-15

少點程式碼,多點頭髮

本文已經被GitHub收錄,歡迎大家踴躍star 和 issues。

https://github.com/midou-tech/articles

入職第一週,我被坑了

最近剛入職新公司,本來想著這剛來新公司,一般都是熟悉熟悉公司同事,看看組內工程文件,找幾個demo自己練練手。

咳咳咳,萬萬沒想到啊,一切都是我以為的,我還是太了。

入職那天下午,組長給我丟了幾個文件,讓我看下這個這些工程的快取系統問題,讓我把redis升級為哨兵模式。

接到任務的我,內心是懵逼的。

第一、不知道都是些什麼型別的服務在用redis。

第二、不知道以什麼姿勢在用redis。

第三、如果redis掛了會不會影響使用者。

第四、我完全沒用過redis。

雖說沒幹過,但咋也不慫。畢竟要是天天干的都是幹過的工作,那就是有問題了,很快就被優化掉了。

看來社招入職和校招還是不一樣的,校招進來都會有些入職培訓或者新人班課程。

通過這些形式的教育,第一、瞭解公司的文化、價值觀,第二、學習工作流程、感受公司技術氛圍。

任務

把我們部門所有使用redis服務升級到哨兵模式。

redis的多種模式

都說了升級到哨兵模式,那之前用的不是哨兵模式,肯定還有其他模式。

單機模式、主從模式、哨兵模式、叢集模式

單機模式

這個最簡單,一看就懂。

就是安裝一個redis,啟動起來,業務呼叫即可。具體安裝步驟和啟動步驟就不贅述了,網上隨便搜一下就有了。

單機在很多場景也是有使用的,例如在一個並非必須保證高可用的情況下。

咳咳咳,其實我們的服務使用的就是redis單機模式,所以來了就讓我改為哨兵模式。

說說單機的優缺點吧。

優點:

  • 部署簡單,0成本。
  • 成本低,沒有備用節點,不需要其他的開支。
  • 高效能,單機不需要同步資料,資料天然一致性。

缺點:

  • 可靠性保證不是很好,單節點有當機的風險。
  • 單機高效能受限於CPU的處理能力,redis是單執行緒的。

單機模式選擇需要根據自己的業務場景去選擇,如果需要很高的效能、可靠性,單機就不太合適了。

主從複製

主從複製,是指將一臺Redis伺服器的資料,複製到其他的Redis伺服器。

前者稱為主節點(master),後者稱為從節點(slave);資料的複製是單向的,只能由主節點到從節點。

主從模式配置很簡單,只需要在從節點配置主節點的ip和埠號即可。

slaveof <masterip> <masterport>
# 例如
# slaveof 192.168.1.214 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服務就如上圖所示,三個哨兵節點,三個主從複製節點。

使用java的jedis去訪問我的redis服務,下面來一段簡單的演示程式碼(並非工程裡面的程式碼):

public static void testSentinel() throws Exception {
     //mastername從配置中獲取或者環境變數,這裡為了演示
         String masterName = "master";
         Set<String> sentinels = new HashSet<>();
     // sentinel的IP一般會從配置檔案獲取或者環境變數,這裡為了演示
         sentinels.add("192.168.200,213:26379");
         sentinels.add("192.168.200.214:26380");
         sentinels.add("192.168.200.215:26381");
 
     //初始化過程做了很多工作
         JedisSentinelPool pool = new JedisSentinelPool(masterName, sentinels); 
     //獲取到redis的client
         Jedis jedis = pool.getResource();
     //寫值到redis
         jedis.set("key1", "value1");
     //讀取資料
     jedis.get("key1");
}

具體部署的配置檔案這裡太長了,需要的朋友可以公眾號後臺回覆【redis配置】獲取。

聽起來是入職第二天就部署了任務感覺很難的樣子。

其實現在看來是個so easy的任務,申請一個redis叢集,自己配置下。在把工程裡面使用到redis的地方改一下,之前使用的是一個兩個單機節點。

幹完,收工。

雖然領導的任務完成了,但並不意味著學習redis的路結束了。愛學習的龍叔,繼續研究了下redis的叢集模式。

叢集模式

主從不能解決故障自動恢復問題,哨兵已經可以解決故障自動恢復了,那到底為啥還要叢集模式呢?

主從和哨兵都還有另外一些問題沒有解決,單個節點的儲存能力是有上限,訪問能力是有上限的。

Redis Cluster 叢集模式具有 高可用可擴充套件性分散式容錯 等特性。

Cluster 叢集模式的原理

通過資料分片的方式來進行資料共享問題,同時提供資料複製和故障轉移功能。

之前的兩種模式資料都是在一個節點上的,單個節點儲存是存在上限的。叢集模式就是把資料進行分片儲存,當一個分片資料達到上限的時候,就分成多個分片。

資料分片怎麼分?

叢集的鍵空間被分割為16384個slots(即hash槽),通過hash的方式將資料分到不同的分片上的。

HASH_SLOT = CRC16(key) & 16384 

CRC16是一種迴圈校驗演算法,這裡不是我們研究的重點,有興趣可以看看。

這裡用了位運算得到取模結果,位運算的速度高於取模運算。

有一個很重要的問題,為什麼是分割為16384個槽?這個問題可能會被面試官隨口一問

資料分片之後怎麼查,怎麼寫?

讀請求分配給slave節點,寫請求分配給master,資料同步從master到slave節點。

讀寫分離提高併發能力,增加高效能。

如何做到水平擴充套件?

master節點可以做擴充,資料遷移redis內部自動完成。

當你新增一個master節點,需要做資料遷移,redis服務不需要下線。

舉個例子:上面的有三個master節點,意味著redis的槽被分為三個段,假設三段分別是0~7000,7001~12000、12001~16383。

現在因為業務需要新增了一個master節點,四個節點共同佔有16384個槽。

槽需要重新分配,資料也需要重新遷移,但是服務不需要下線。

redis叢集的重新分片由redis內部的管理軟體redis-trib負責執行。redis提供了進行重新分片的所有命令,redis-trib通過向節點傳送命令來進行重新分片。

如何做故障轉移?

假如途中紅色的節點故障了,此時master3下面的從節點會通過 選舉 產生一個主節點。替換原來的故障節點。

此過程和哨兵模式的故障轉移是一樣的。

總結

每種模式都有各自的優缺點,在實際使用場景中要根據業務特點去選擇合適的模式。

redis是一個非常常用的中介軟體,作為一個使用者來說,學習成本一點不高。

如果作為一個很好的中介軟體去研究的話,還是有很多值得學習和借鑑的地方。比如redis的各種資料結構(動態字串、跳躍表、集合、字典等)、高效的記憶體分配(jemalloc)、高效的IO模型等等。

每個點都可以深入研究,在後期設計高併發、高可用系統的時候融入進去。

我是龍叔,一個分享網際網路技術和成長心路歷程的star。

相關文章