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

少點代碼,多點頭髮

本文已經被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。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※推薦評價好的iphone維修中心

您可能也會喜歡…