Redis叢集最佳實踐
儲存系統通用解決方案
資料量大查詢慢:歷史資料歸檔/分庫分表 =》 分片
併發高扛不住:讀寫分離 =》 增加例項數
主例項宕機:增加主從節點,主節點宕機時候從節點頂上 =》主從複製(資料一致性問題)
Redis Cluster如何應對資料量大、高併發和高可用問題?
一、分片
槽(Slot):每個叢集16*1024=16384個Slot,槽是Redis分片的基本單位,每個槽存放部分Key
雜湊Key:HASH_SLOT = CRC16(key) mod 16384
槽如何存放Redis節點:利用查表法
客戶端連線任意節點訪問叢集資料,訪問Key, 通過HASH_SLOT公式計算具體的槽位,再通過查表法,查詢到槽與節點的真實對映關係,再重定向到正確節點上
二、水平擴容
利用水平擴容增加叢集儲存容量,叢集新增節點,從叢集老節點搬運部分槽到新節點,也可以手動指定具體的槽到新節點 =》利用官方的 redis-trib.rb指令碼自動重新分配槽,自動遷移
三、高可用&高併發
高可用:增加主從節點,做主從複製;
Redis Cluster支援每個分片增加1個或多個從節點,從節點連線主節點後,向主節點發送SYNC命令 ,請求一次全量複製;全量複製完後,進入同步階段,主節點把剛剛複製期間收到的全部命令以及後續收到命令,持續轉發給從節點; =》狀態機技術(快照+日誌)
高併發:主從節點讀取,大部分讀寫都是主節點負責,從節點只是預備作用
四、Redis Cluster不適合超大規模叢集的原因
Redis Cluster優點:易使用,分片、主從複製、彈性擴容功能自動化,簡單部署並可達到大容量、高可靠、高可用的Redis叢集,對應用來說,完全透明,適合構建中小規模Redis叢集(幾10個規模Redis叢集)
不適合超大規模叢集原因:去中心化設計,Redis每個節點儲存所有槽和節點對映關係
問題:這個對映關係是如何更新的?叢集中加入新節點或某個節點宕機,新節點被選舉出來,都需要更新叢集每個節點對映關係
實現:採用流言(Gossip)協議 https://en.wikipedia.org/wiki/Gossip_protocol 八卦傳播協議,優點:避免中心節點故障,缺點:傳輸速度慢,叢集規模越大,傳播協議越慢;叢集規模太大,資料不同步問題明顯放大,存在一定不確定性,問題難排查
方案一:代理模式
優點: 代理實現路由轉發,檢測叢集Redis節點狀態(出現問題及時切換),維護叢集元資料
缺點:增加一層代理轉發,資料鏈路更長,帶來一定效能損失;代理服務同樣需要叢集支援
業界方案:twemproxy (https://github.com/twitter/twemproxy )和codis (https://github.com/CodisLabs/codis)
方案二:客戶端定址 (推薦)
實現原理:客戶端維護元資料,某個分片主節點宕機,新節點選舉出來,更新元資料資訊
問題:元資料服務依舊是單點,可以使用Zookeeper、etcd或MySQL解決
優點: 效能、彈性、高可用幾方面表現都非常好
缺點:整個架構比較複雜,客戶端不能通用;需要定製Redis客戶端