最通俗易懂的 Redis 架構模式詳解

前言

  

  話說有一名意大利程序員,在 2004 年到 2006 年間主要作嵌入式工做,以後接觸了 Web,2007 年和朋友共同建立了一個網站,併爲瞭解決這個網站的負載問題(爲了不 MySQL 的低性能),因而親自定作一個數據庫,並於 2009 年開發完成,這個就是 Redis。這個意大利程序員就是 Salvatore Sanfilippo 江湖人稱 Redis 之父,你們更習慣稱呼他 Antirez。程序員

  

  

  Redis 技術愈來愈火爆,其超高的性能,簡潔輕量的設計,易上手,分佈式架構的支持,在緩存等領域出色的表現造就了它如今的地位。redis

  官方的 Benchmark 數據:測試完成了 50 個併發執行 10W 個請求。設置和獲取的值是一個 256 字節字符串。算法

  結果:讀的速度是 110000次/s,寫的速度是 81000次/s。數據庫

  爲了知足開發市場需求,Redis 支持單機主從哨兵集羣多種架構模式,本文帶你們詳細講解這幾種架構模式的區別。緩存

  

單機模式

  單機模式顧名思義就是安裝一個 Redis,啓動起來,業務調用便可。例如一些簡單的應用,並不是必須保證高可用的狀況下可使用該模式。服務器

  

優勢

  

  • 部署簡單;
  • 成本低,無備用節點;
  • 高性能,單機不須要同步數據,數據自然一致性。

  

缺點

  

  • 可靠性保證不是很好,單節點有宕機的風險。
  • 單機高性能受限於 CPU 的處理能力,Redis 是單線程的。

  

  單機 Redis 可以承載的 QPS(每秒查詢速率)大概在幾萬左右。取決於業務操做的複雜性,Lua 腳本複雜性就極高。假如是簡單的 key value 查詢那性能就會很高。網絡

  假設上千萬、上億用戶同時訪問 Redis,QPS 達到 10 萬+。這些請求過來,單機 Redis 直接就掛了。系統的瓶頸就出如今 Redis 單機問題上,此時咱們能夠經過主從複製解決該問題,實現系統的高併發。架構

  

主從複製

  Redis 的複製(Replication)功能容許用戶根據一個 Redis 服務器來建立任意多個該服務器的複製品,其中被複制的服務器爲主服務器(Master),而經過複製建立出來的複製品則爲從服務器(Slave)。 只要主從服務器之間的網絡鏈接正常,主服務器就會將寫入本身的數據同步更新給從服務器,從而保證主從服務器的數據相同。併發

  數據的複製是單向的,只能由主節點到從節點,簡單理解就是從節點只支持讀操做,不容許寫操做。主要是讀高併發的場景下用主從架構。主從模式須要考慮的問題是:當 Master 節點宕機,須要選舉產生一個新的 Master 節點,從而保證服務的高可用性。運維

  

優勢

  

  • Master/Slave 角色方便水平擴展,QPS 增長,增長 Slave 便可;
  • 下降 Master 讀壓力,轉交給 Slave 節點;
  • 主節點宕機,從節點做爲主節點的備份能夠隨時頂上繼續提供服務;

  

缺點

  

  • 可靠性保證不是很好,主節點故障便沒法提供寫入服務;
  • 沒有解決主節點寫的壓力;
  • 數據冗餘(爲了高併發、高可用和高性能,通常是容許有冗餘存在的);
  • 一旦主節點宕機,從節點晉升成主節點,須要修改應用方的主節點地址,還須要命令全部從節點去複製新的主節點,整個過程須要人工干預;
  • 主節點的寫能力受到單機的限制;
  • 主節點的存儲能力受到單機的限制。

  

哨兵模式

  主從模式中,當主節點宕機以後,從節點是能夠做爲主節點頂上來繼續提供服務,可是須要修改應用方的主節點地址,還須要命令全部從節點去複製新的主節點,整個過程須要人工干預。

  因而,在 Redis 2.8 版本開始,引入了哨兵(Sentinel)這個概念,在主從複製的基礎上,哨兵實現了自動化故障恢復。如上圖所示,哨兵模式由兩部分組成,哨兵節點和數據節點:

  • 哨兵節點:哨兵節點是特殊的 Redis 節點,不存儲數據;
  • 數據節點:主節點和從節點都是數據節點。

  

  Redis Sentinel 是分佈式系統中監控 Redis 主從服務器,並提供主服務器下線時自動故障轉移功能的模式。其中三個特性爲:

  • 監控(Monitoring):Sentinel 會不斷地檢查你的主服務器和從服務器是否運做正常;
  • 提醒(Notification):當被監控的某個 Redis 服務器出現問題時, Sentinel 能夠經過 API 向管理員或者其餘應用程序發送通知;
  • 自動故障遷移(Automatic failover):當一個主服務器不能正常工做時, Sentinel 會開始一次自動故障遷移操做。

  

  接下來咱們瞭解一些 Sentinel 中的關鍵名詞,而後系統講解下哨兵模式的工做原理。

  

定時任務

  

  Sentinel 內部有 3 個定時任務,分別是:

  • 每 1 秒每一個 Sentinel 對其餘 Sentinel 和 Redis 節點執行 PING 操做(監控),這是一個心跳檢測,是失敗斷定的依據。
  • 每 2 秒每一個 Sentinel 經過 Master 節點的 channel 交換信息(Publish/Subscribe);
  • 每 10 秒每一個 Sentinel 會對 Master 和 Slave 執行 INFO 命令,這個任務主要達到兩個目的:
    • 發現 Slave 節點;
    • 確認主從關係。

  

主觀下線

  

  所謂主觀下線(Subjectively Down, 簡稱 SDOWN)指的是單個 Sentinel 實例對服務器作出的下線判斷,即單個 Sentinel 認爲某個服務下線(有多是接收不到訂閱,之間的網絡不通等等緣由)。

  主觀下線就是說若是服務器在給定的毫秒數以內, 沒有返回 Sentinel 發送的 PING 命令的回覆, 或者返回一個錯誤, 那麼 Sentinel 會將這個服務器標記爲主觀下線(SDOWN)。

  

客觀下線

  

  客觀下線(Objectively Down, 簡稱 ODOWN)指的是多個 Sentinel 實例在對同一個服務器作出 SDOWN 判斷,而且經過命令互相交流以後,得出的服務器下線判斷,而後開啓 failover。

  只有在足夠數量的 Sentinel 都將一個服務器標記爲主觀下線以後, 服務器纔會被標記爲客觀下線(ODOWN)。只有當 Master 被認定爲客觀下線時,纔會發生故障遷移。

  

仲裁

  

  仲裁指的是配置文件中的 quorum 選項。某個 Sentinel 先將 Master 節點標記爲主觀下線,而後會將這個斷定經過 sentinel is-master-down-by-addr 命令詢問其餘 Sentinel 節點是否也一樣認爲該 addr 的 Master 節點要作主觀下線。最後當達成這一共識的 Sentinel 個數達到前面說的 quorum 設置的值時,該 Master 節點會被認定爲客觀下線並進行故障轉移。

  quorum 的值通常設置爲 Sentinel 個數的二分之一加 1,例如 3 個 Sentinel 就設置爲 2。

  

哨兵模式工做原理

  

  1. 每一個 Sentinel 以每秒一次的頻率向它所知的 Master,Slave 以及其餘 Sentinel 節點發送一個 PING 命令;
  2. 若是一個實例(instance)距離最後一次有效回覆 PING 命令的時間超過配置文件 own-after-milliseconds 選項所指定的值,則這個實例會被 Sentinel 標記爲主觀下線
  3. 若是一個 Master 被標記爲主觀下線,那麼正在監視這個 Master 的全部 Sentinel 要以每秒一次的頻率確認 Master 是否真的進入主觀下線狀態;
  4. 當有足夠數量的 Sentinel(大於等於配置文件指定的值)在指定的時間範圍內確認 Master 的確進入了主觀下線狀態,則 Master 會被標記爲客觀下線
  5. 若是 Master 處於 ODOWN 狀態,則投票自動選出新的主節點。將剩餘的從節點指向新的主節點繼續進行數據複製;
  6. 在正常狀況下,每一個 Sentinel 會以每 10 秒一次的頻率向它已知的全部 Master,Slave 發送 INFO 命令;當 Master 被 Sentinel 標記爲客觀下線時,Sentinel 向已下線的 Master 的全部 Slave 發送 INFO 命令的頻率會從 10 秒一次改成每秒一次;
  7. 若沒有足夠數量的 Sentinel 贊成 Master 已經下線,Master 的客觀下線狀態就會被移除。若 Master 從新向 Sentinel 的 PING 命令返回有效回覆,Master 的主觀下線狀態就會被移除。

  

優勢

  

  • 哨兵模式是基於主從模式的,全部主從的優勢,哨兵模式都有;
  • 主從能夠自動切換,系統更健壯,可用性更高;
  • Sentinel 會不斷地檢查你的主服務器和從服務器是否運做正常。當被監控的某個 Redis 服務器出現問題時, Sentinel 能夠經過 API 向管理員或者其餘應用程序發送通知。

  

缺點

  

  • 主從切換須要時間,會丟失數據;

  • 仍是沒有解決主節點寫的壓力;

  • 主節點的寫能力,存儲能力受到單機的限制;

  • 動態擴容困難複雜,對於集羣,容量達到上限時在線擴容會變得很複雜。

  

集羣模式

  

  假設上千萬、上億用戶同時訪問 Redis,QPS 達到 10 萬+。這些請求過來,單機 Redis 直接就掛了。系統的瓶頸就出如今 Redis 單機問題上,此時咱們能夠經過主從複製解決該問題,實現系統的高併發。

  主從模式中,當主節點宕機以後,從節點是能夠做爲主節點頂上來繼續提供服務,可是須要修改應用方的主節點地址,還須要命令全部從節點去複製新的主節點,整個過程須要人工干預。因而,在 Redis 2.8 版本開始,引入了哨兵(Sentinel)這個概念,在主從複製的基礎上,哨兵實現了自動化故障恢復

  哨兵模式中,單個節點的寫能力,存儲能力受到單機的限制,動態擴容困難複雜。因而,Redis 3.0 版本正式推出 Redis Cluster 集羣模式,有效地解決了 Redis 分佈式方面的需求。Redis Cluster 集羣模式具備高可用可擴展性分佈式容錯等特性。

  

  

  Redis Cluster 採用無中心結構,每一個節點均可以保存數據和整個集羣狀態,每一個節點都和其餘全部節點鏈接。Cluster 通常由多個節點組成,節點數量至少爲 6 個才能保證組成完整高可用的集羣,其中三個爲主節點,三個爲從節點。三個主節點會分配槽,處理客戶端的命令請求,而從節點可用在主節點故障後,頂替主節點。

  如上圖所示,該集羣中包含 6 個 Redis 節點,3 主 3 從,分別爲 M1,M2,M3,S1,S2,S3。除了主從 Redis 節點之間進行數據複製外,全部 Redis 節點之間採用 Gossip 協議進行通訊,交換維護節點元數據信息。

  總結下來就是:讀請求分配給 Slave 節點,寫請求分配給 Master,數據同步從 Master 到 Slave 節點。

  

分片

  

  單機、主從、哨兵的模式數據都是存儲在一個節點上,其餘節點進行數據的複製。而單個節點存儲是存在上限的,集羣模式就是把數據進行分片存儲,當一個分片數據達到上限的時候,還能夠分紅多個分片。

  Redis Cluster 採用虛擬哈希槽分區,全部的鍵根據哈希函數映射到 0 ~ 16383 整數槽內,計算公式:HASH_SLOT = CRC16(key) % 16384。每個節點負責維護一部分槽以及槽所映射的鍵值數據。

  Redis Cluster 提供了靈活的節點擴容和縮容方案。在不影響集羣對外服務的狀況下,能夠爲集羣添加節點進行擴容也能夠下線部分節點進行縮容。能夠說,槽是 Redis Cluster 管理數據的基本單位,集羣伸縮就是槽和數據在節點之間的移動。

  簡單的理解就是:擴容或縮容之後,槽須要從新分配,數據也須要從新遷移,可是服務不須要下線。

  

  假如,這裏有 3 個節點的集羣環境以下:

  • 節點 A 哈希槽範圍爲 0 ~ 5500;
  • 節點 B 哈希槽範圍爲 5501 ~ 11000;
  • 節點 C 哈希槽範圍爲 11001 ~ 16383。

  此時,咱們若是要存儲數據,按照 Redis Cluster 哈希槽的算法,假設結果是: CRC16(key) % 16384 = 6782。 那麼就會把這個 key 的存儲分配到 B 節點。此時鏈接 A、B、C 任何一個節點獲取 key,都會這樣計算,最終經過 B 節點獲取數據。

  假如這時咱們新增一個節點 D,Redis Cluster 會從各個節點中拿取一部分 Slot 到 D 上,好比會變成這樣:

  • 節點 A 哈希槽範圍爲 1266 ~ 5500;
  • 節點 B 哈希槽範圍爲 6827 ~ 11000;
  • 節點 C 哈希槽範圍爲 12288 ~ 16383;
  • 節點 D 哈希槽範圍爲 0 ~ 1265,5501 ~ 6826,11001 ~ 12287

  這種特性容許在集羣中輕鬆地添加和刪除節點。一樣的若是我想刪除節點 D,只須要將節點 D 的哈希槽移動到其餘節點,當節點是空時,即可徹底將它從集羣中移除。

  

主從模式

  

  Redis Cluster 爲了保證數據的高可用性,加入了主從模式,一個主節點對應一個或多個從節點,主節點提供數據存取,從節點複製主節點數據備份,當這個主節點掛掉後,就會經過這個主節點的從節點選取一個來充當主節點,從而保證集羣的高可用。

  回到剛纔的例子中,集羣有 A、B、C 三個主節點,若是這 3 個節點都沒有對應的從節點,若是 B 掛掉了,則集羣將沒法繼續,由於咱們再也不有辦法爲 5501 ~ 11000 範圍內的哈希槽提供服務。

  因此咱們在建立集羣的時候,必定要爲每一個主節點都添加對應的從節點。好比,集羣包含主節點 A、B、C,以及從節點 A一、B一、C1,那麼即便 B 掛掉系統也能夠繼續正確工做。

  由於 B1 節點屬於 B 節點的子節點,因此 Redis 集羣將會選擇 B1 節點做爲新的主節點,集羣將會繼續正確地提供服務。當 B 從新開啓後,它就會變成 B1 的從節點。可是請注意,若是節點 B 和 B1 同時掛掉,Redis Cluster 就沒法繼續正確地提供服務了。

  

優勢

  

  • 無中心架構;
  • 可擴展性,數據按照 Slot 存儲分佈在多個節點,節點間數據共享,節點可動態添加或刪除,可動態調整數據分佈;
  • 高可用性,部分節點不可用時,集羣仍可用。經過增長 Slave 作備份數據副本。
  • 實現故障自動 failover,節點之間經過 gossip 協議交換狀態信息,用投票機制完成 Slave 到 Master 的角色提高。

  

缺點

  

  • 數據經過異步複製,沒法保證數據強一致性
  • 集羣環境搭建複雜,不過基於 Docker 的搭建方案會相對簡單。

  

總結

  

  隨着互聯網的飛速發展,咱們享受着技術帶來的便利,同時也給從業者帶來了如何保證項目高併發、低延時的技術挑戰。Redis 以其超高的性能,簡潔輕量的設計,易上手,分佈式架構的支持,在緩存等領域出色的表現等,獲得了業界普遍的關注和應用,在當今高性能架構中,也發揮着愈來愈重要的做用。甚至能夠說,Redis 已經成爲 IT 互聯網大型系統的標配,熟練掌握 Redis 成爲開發、運維人員的必備技能。

  若是不深挖底層,僅僅只是從使用的角度出發,Redis 的學習成本將會很是低。若是做爲一個很好的中間件去研究的話,仍是有不少值得學習和借鑑的地方。以上幾種模式,每種都有各自的優缺點,在實際場景中要根據業務特色去選擇合適的模式使用。

  

參考資料

  

本文采用 知識共享「署名-非商業性使用-禁止演繹 4.0 國際」許可協議

你們能夠經過 分類 查看更多關於 Redis 的文章。

  

🤗 您的點贊轉發是對我最大的支持。

📢 掃碼關注 哈嘍沃德先生「文檔 + 視頻」每篇文章都配有專門視頻講解,學習更輕鬆噢 ~

相關文章
相關標籤/搜索