redis4.0、codis、阿里雲redis 3種redis集群對比分析
摘要: 本文對redis4.0版本的cluster,codis,以及阿里雲redis 3種集群進行了對比分析。
1、架構對比
1.1、redis 4.0 cluster
redis 4.0版本的集群是去中心化的結構,集群元數據信息分布在每個節點上,主備切換依賴於多個節點協商選主。
redis 提供了redis-trib 工具做部署集群及運維等操作。
客戶端訪問散列的db節點需依賴smart client,也就是客戶端需要對redis返回的節點信息做判斷選擇路由等操作。例如客戶端請求一個節點,如果所請求的key不在該節點上,客戶端需要判斷返回的move或ask等指令,重定向請求到對應的節點。
1.2、codis
codis由3大組件構成:
- codis-server : 修改過源碼的redis, 支持slot,擴容遷移等
- codis-proxy : 支持多線程,go語言實現的內核
- codis Dashboard : 集群管理工具
提供web圖形界面管理集群。
集群元數據存在在zookeeper或etcd。
提供獨立的組件codis-ha負責redis節點主備切換。
基於proxy的codis,客戶端對路由表變化無感知。客戶端需要從codis dashhoard調用list proxy命令獲取所有proxy列表,並根據自身的輪詢策略決定訪問哪個proxy節點以實現負載均衡。
1.3、阿里雲redis
阿里雲的redis集群版由3大組件構成:
- redis-config : 集群管理工具
- redis-server : 優化過源碼的redis,支持slot, 擴容遷移等
- redis-proxy : 單線程,c++14語言實現的內核
架構圖如下:
redis-proxy 無狀態,一個集群根據集群規格可掛多個proxy節點。
redis-config 雙節點,支持容災。
集群元數據存儲在rds db上。
提供獨立的組件HA負責集群的主備切換等。
阿里雲的redis集群同樣基於proxy,用戶對路由信息無感知,同時提供vip給客戶端訪問,客戶端只需一個連接地址即可,無須關心proxy訪問的負載均衡等。
2、性能對比
2.1、壓測環境
在3台物理機上分別搭建了以上3種redis集群。每台物理機千兆網卡,24核cpu,內存189G。3台物理機分別跑壓測工具memtier_benchmark、codis proxy/阿里雲proxy、redis server。redis server使用各種集群配套的redis內核。
固定key size 32個位元組,set/get 操作比例為1:10。每個線程16個客戶端。連續壓測5分鐘,分8個, 16個, 32個, 48個, 64個線程壓測。
因為redis4.0集群需要額外的客戶端選擇節點,而memtier_benchmark不支持,所以使用了hashtag 來壓測redis4.0。
每個集群有8個master db, 8個slave db, aof打開。aof rewrite的最小buffer為64MB。
壓測的對象分別為單個redis 4.0 節點, 單個阿里雲redis-proxy, 單核的codis-proxy, 8核的codis-proxy。
codis 使用的go版本為1.7.4。
壓測結果圖如下:
可看出,單核的codis-proxy性能最弱。8核的codis-proxy壓測沒有對key使用hashtag,如此相當於將請求分散到後端8個db節點上, 也可以說相當於8個阿里雲的redis-proxy。自然性能數據就比較高了。
單核的阿里雲redis-proxy在壓力夠大的情況下性能逼近原生的redis db節點。
在實際生產環境中,使用原生的redis cluster,客戶端需要實現cluster protocol, 解析move, ask等指令並重定向節點,隨意訪問key可能需要兩次訪問操作才能完成,性能上並不能完全如單節點一樣。
3、支持特性對比
3.1、主要不同協議的支持對比
更多命令請參考各自的集群版本說明。
3.2、水平擴展對比
redis4.0 cluster,codis,阿里雲redis 分散式集群均實現了面對slot的管理,擴展的最小單元是slot。
分散式集群中水平擴展的本質是對集群節點的路由信息管理以及數據的遷移。這3種集群遷移數據的最小單位均是key。
3.2.1 redis cluster 水平擴展原理
redis4.0 cluster支持指定slot在節點中移動,也支持加入空節點後根據集群節點中已存在的slot分布自動進行再分布。以redis-trib的move_slot為例解析slot移動的過程:
- 步驟1): 調用setslot命令修改源、目標節點slot的狀態
- 步驟2): 獲取源節點上slot的key列表
- 步驟3): 調migrate命令遷移key,遷移過程中redis屬於阻塞狀態,只有目標節點restore成功後才返回
- 步驟4): 調用setslot命令修改源、目標節點slot的狀態
在遷移過程中,如何保證數據的一致性呢?
redis cluster提供遷移狀態中的重定向機制,向客戶端返回ASK,客戶端收到後需先發送asking指令到目標節點上,然後再發請求到目標節點上才可以訪問。當訪問的key滿足以下全部條件時會出現重定向返回:
- key所屬slot在該節點上,如不在,返回的是MOVE
- slot處於遷移狀態中
- key不存在
如上所述,migrate 是一個同步阻塞型的操作,如果key並不為空,即使slot處於遷移狀態,key依然能被讀寫,以此保證數據的一致性。
3.2.2 codis 水平擴展原理
codis對slot的再分布策略與redis cluster相同。codis-server內核並沒有存儲slot的信息,也不解析key所在的slot,只有在dbadd等操作時將對應的key記錄到以slot為key的dict中,如果key帶有tag,則將tag做crc32運算後將key插入到以crc32值為key的skiplist中。
codis Dashboard 後台起遷移狀態機程序,先確保通知到所有proxy開始遷移,即prepare階段,如有一台以上proxy失敗,則遷移任務失敗。遷移步驟與redis cluster類似,不同點是:
- slot狀態信息存儲在zookeeper/etcd
- 發送slotsmgrttagslot而非migrate指令,slotsmgrttagslot執行時會隨機獲取一個key遷移,如key帶有tag,則從上文中的skiplist獲取所有key批量遷移
codis同樣也是同步阻塞型的遷移操作。
在保持數據一致性方面,因為codis-server內核不維護slot的狀態,所以一致性的保證落在了proxy組件上。codis-proxy在處理請求時,先判斷key所在slot的狀態,如slot處於遷移中,則向codis-server發起指定key遷移的命令,等key遷移完成後,codis-proxy轉向目標的codis-server請求。做法簡單,對redis內核修改較少,但同時也導致遷移慢,客戶端卡住的時間較久。
3.2.3 阿里雲redis 水平擴展原理
阿里雲redis除了提供指定源、節點、slot外,還提供按節點的容量、slot的大小等考量參數動態分配slot,以最小粒度影響集群可用性作為分配原則。遷移大體步驟如下:
- 步驟1): 由redis-config計算源、目標節點、slot
- 步驟2): redis-config向redis-server發送遷移slot指令
- 步驟3): redis-server啟動遷移狀態機,分批量遷移key
- 步驟4): redis-config定時檢查redis-server並更新slot狀態
與codis不同,阿里雲redis在內核上同樣維護了slot的信息,並且拋棄了codis遷移整個slot和redis cluster遷移單個key的做法,從內核上支持批量遷移,加快遷移速度。
阿里雲redis遷移數據是非同步的流程,不等待目標節點是否restore成功,由目標節點通知和源節點定時檢查來驗證是否成功。以此縮小同步阻塞對其他slot訪問的影響。
同時也是因為遷移非同步化,所以在保證數據一致性時,判斷請求如果是寫請求並且key存在且不在遷移的key列表中,走正常的寫請求流程。其他數據一致性保證與redis4.0 cluster相同。
阿里雲redis-server優化了遷移大key的流程,詳情可見https://yq.aliyun.com/articles/64884?spm=5176.8091938.0.0.fF3UZH
3.3、其他
阿里雲的redis內核和proxy的熱升級過程中均不斷連接,對客戶端無影響。
4、結束語
雲資料庫Redis版(ApsaraDB for Redis)是一種穩定可靠、性能卓越、可彈性伸縮的資料庫服務。基於飛天分散式系統和全SSD盤高性能存儲,支持主備版和集群版兩套高可用架構。提供了全套的容災切換、故障遷移、在線擴容、性能優化的資料庫解決方案。歡迎各位購買使用:雲資料庫 Redis 版
作者:羽洵
更多技術乾貨敬請關注云棲社區知乎機構號:阿里云云棲社區 - 知乎
推薦閱讀:
※B+樹並發協議
※怎樣操作leveldb資料庫,實現增刪改查?
※終於等到你——MySQL 5.7與PostgreSQL 9.6的百萬QPS大比拼
※如何實現基於 follow 關係的 timeline?
※如何安裝與連接MySQL?