redis 集羣方案主要有兩類,一是使用類 codis 的架構,按組劃分,實例之間互相獨立;
另外一套是基於官方的 redis cluster 的方案;下面分別聊聊這兩種方案;mysql
這套架構的特色:git
使用這套方案的公司:
阿里雲: ApsaraCache, RedisLabs、京東、百度等github
slots 方案:劃分了 1024個slot, slots 信息在 proxy層感知; redis 進程中維護本實例上的全部key的一個slot map;golang
遷移過程當中的讀寫衝突處理:
最小遷移單位爲key;
訪問邏輯都是先訪問 src 節點,再根據結果判斷是否須要進一步訪問 target 節點;redis
AparaCache 的單機版已開源(開源版本中不包含slot等實現),集羣方案細節未知;ApsaraCache算法
主要組件:
proxy,基於twemproxy 改造,實現了動態路由表;
redis內核: 基於2.x 實現的slots 方案;
metaserver:基於redis實現,包含的功能:拓撲信息的存儲 & 探活;
最多支持1000個節點;sql
slot 方案:
redis 內核中對db劃分,作了16384個db; 每一個請求到來,首先作db選擇;架構
數據遷移實現:
數據遷移的時候,最小遷移單位是slot,遷移中整個slot 處於阻塞狀態,只支持讀請求,不支持寫請求;
對比 官方 redis cluster/ codis 的按key粒度進行遷移的方案:按key遷移對用戶請求更爲友好,但遷移速度較慢;這個按slot進行遷移的方案速度更快;阿里雲
主要組件:
proxy: 自主實現,基於 golang 開發;
redis內核:基於 redis 2.8
configServer(cfs)組件:配置信息存放;
scala組件:用於觸發部署、新建、擴容等請求;
mysql:最終全部的元信息及配置的存儲;
sentinal(golang實現):哨兵,用於監控proxy和redis實例,redis實例失敗後觸發切換;線程
slot 方案實現:
在內存中維護了slots的map映射表;
數據遷移:
基於 slots 粒度進行遷移;
scala組件向dst實例發送命令告知會接受某個slot;
dst 向 src 發送命令請求遷移,src開啓一個線程來作數據的dump,將這個slot的數據整塊dump發送到dst(未加鎖,只讀操做)
寫請求會開闢一塊緩衝區,全部的寫請求除了寫原有數據區域,同時雙寫到緩衝區中。
當一個slot遷移完成後,把這個緩衝區的數據都傳到dst,當緩衝區爲空時,更改本分片slot規則,再也不擁有該slot,後續再請求這個slot的key返回moved;
上層proxy會保存兩份路由表,當該slot 請求目標實例獲得 move 結果後,更新拓撲;
跨機房:跨機房使用主從部署結構;沒有多活,異地機房做爲slave;
和上一套方案比,全部功能都集成在 redis cluster 中,路由分片、拓撲信息的存儲、探活都在redis cluster中實現;各實例間經過 gossip 通訊;這樣的好處是簡單,依賴的組件少,應對400個節點之內的場景沒有問題(按單實例8w read qps來計算,可以支持 200 * 8 = 1600w 的讀多寫少的場景);但當須要支持更大的規模時,因爲使用 gossip協議致使協議之間的通訊消耗太大,redis cluster 再也不合適;
使用這套方案的有:AWS, 百度貼吧
數據遷移過程:
基於 key粒度的數據遷移;
遷移過程的讀寫衝突處理:
從A 遷移到 B;
ElasticCache 支持主從和集羣版、支持讀寫分離;
集羣版用的是開源的Redis Cluster,未作深度定製;
基於redis cluster + twemproxy 實現;後被 BDRP 吞併;
twemproxy 實現了 smart client 功能;使用 redis cluster後還加一層 proxy的好處:
即將發佈的 redis 5.0 中有個 feature,做者計劃給 redis cluster加一個proxy。
ksarch-saas 對 twemproxy的改造已開源:
https://github.com/ksarch-saas/r3proxy