結論
有以下幾種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