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