架構師必備:Redis的幾種叢集方案

Java烘焙師發表於2022-04-30

結論

有以下幾種Redis叢集方案,先說結論:

  • Redis cluster:應當優先考慮使用Redis cluster。
  • codis:舊專案如果仍在使用codis,可繼續使用,但也推薦遷移到Redis cluster。
  • twemproxy:不建議使用,與codis同為proxy方案,但不如codis(twemproxy不能平滑地擴容)。
  • 客戶端分片:應當禁止使用,因為擴容複雜,如果2個服務同時讀寫,其中一個修改了路由,另一個不修改會有問題。

下面重點介紹Redis cluster和codis。

Redis cluster原理

架構

是官方支援的Redis叢集方案:

  • 去中心化架構,不依賴外部儲存,每個節點都有槽位資訊、以及一部分資料,各節點之間使用gossip協議互動資訊
  • 劃分為16384個slot槽位,每個key按照分片規則,對key做crc16 % 16384得到slot id
  • 每個Redis節點儲存了一部分槽位資料,各個Redis節點共同分擔16384個slot槽位
  • 客戶端需遵守Redis cluster規範讀寫資料,客戶端連線叢集時,會得到一份叢集的槽位配置資訊,客戶端本地快取了slot到node的對映關係,以便直接定位到對應的Redis節點
    • 用key計算出slot
    • 通過本地快取的slot到node對映關係(某個slot範圍對映到某個node),用slot得出node
    • 請求對應的node節點,如果key對應的槽位在Redis節點儲存的各槽位中,則查詢結果
    • 如果key對應的槽位不在Redis節點儲存的各槽位中(即key所在的槽位不歸該節點管理),則返回moved <節點> 提示客戶端再次請求指定的節點,並更新本地對映關係
    • 如果請求的key對應槽位正在遷移,則返回ask <節點> 提示客戶端再次請求指定的節點
  • 主庫讀寫,從庫用於高可用備份、一般不用來承擔讀請求:主從同步通過指令流、環形陣列來做增量同步,通過RDB來做全量同步

優點

  • 官方支援的叢集方案,能使用最新feature
  • 效能好,無多餘網路開銷
  • 無一致性問題,讀寫請求都走主節點
  • 槽位更精細,16384(2^14)相比於codis的1024

缺點

  • 如果是從舊版不支援叢集的Redis升級而來,需做較大改造,把傳統的Jedis client需替換成智慧客戶端來維護key到slot的對映關係,如lettuce
  • 官方是最小使用原則,沒有易用的擴容、遷移工具,需要尋找社群提供的易用介面,或自行研發
  • 遷移過程中效能可能受影響,有3次請求:首次get得到ask返回、再次asking確認指定節點是否有槽位、最後get

codis原理

架構

是Go語言編寫的Redis proxy叢集方案:

  • codis-proxy作為上層proxy,負責路由請求至底層的Redis分片。client與proxy互動,可以把proxy當作普通的Redis例項一樣,因為codis-proxy實現了Redis協議,API保持一致。
  • Redis分片是一個codis-group,包括了多個codis-server,其中有1個主節點、n個從節點,用來作讀寫分離,主節點承擔寫請求,從節點分攤讀請求。各個分片的Redis例項是獨立的,互不感知。codis-server與普通Redis例項的區別是,在Redis的基礎上擴充套件實現了slot槽的功能,用於擴容、資料遷移。
  • 分片規則:對key做crc32 % 1024
  • 強依賴zookeeper,來儲存節點槽位資訊。
  • codis-dashboard、codis-fe是叢集運維工具。

優點

  • 客戶端無需感知背後細節,使用起來跟Redis單例項無明顯區別(除部分命令不支援)
  • 平滑擴容,運維操作簡單,有易於使用的web介面

缺點

  • 是在Redis官方未支援叢集方案之前的可選方案,目前已停止更新
  • proxy會帶來額外的網路開銷,請求鏈路多了一層
  • 讀寫分離可能出現不一致的問題,也需要評估請求讀寫比
  • 需要額外維護zookeeper

相關文章