Redis在豌豆莢的使用歷程——單實例==》多實例,業務代碼中做sharding==》單個Twemproxy==》多個Twemproxy==》Codis,豌豆莢自己開發的分布式Redis服務。在大規模的Redis使用過程中,他們發現Redis受限于多個方面:單機內存有限、帶寬壓力、單點問題、不能動態擴容以及磁盤損壞時的數據搶救。
Redis通常有3個使用途徑:客戶端靜態分片,一致性哈希;通過Proxy分片,即Twemproxy;還有就是官方的Redis Cluster,但至今無一個新版本。隨后劉奇更詳細的分析了為什么不使用Twemproxy和Redis Cluster:
Twemproxy:最大的痛點是無法平滑的擴容或者縮容,甚至修改配置都需要重啟服務;其次,不可運維,甚至沒有Dashboard。
Redis Cluster(官方):無中心化設計,程序難以編寫;代碼有點嚇人,clusterProcessPacket函數有426行,人腦難以處理所有的狀態切換;遲遲沒有正式版本,等了4年之久;目前還缺乏最佳實踐,沒有人編寫Redis Cluster的若干條注意事項;整個系統高度耦合,升級困難。
雖然我們有眾多的選擇,比如Tair、Couchbase等,但是如果你需要更復雜和優秀的數據結構,Redis可稱為不二之選。基于這個原因,在Redis之上,豌豆莢設計了Codis,并將之開源。
Codis
既然重新設計,那么Codis首先必須滿足自動擴容和縮容的需求,其次則是必須避免單點故障和單點帶寬不足,做一個高可用的系統。在這之后,基于原有的遺留系統,還必須可以輕松地將數據從Twemproxy遷移到Codis,并實現良好的運維和監控。基于這些,Codis的設計躍然紙面:
然而,一個新系統的開發并不是件容易的事情,特別是一個復雜的分布式系統。劉奇表示,雖然當時團隊只有3個人,但是他們幾乎考量了可以考量的各種細節:
- 盡量拆分,簡化每個模塊,同時易于升級
- 每個組件只負責自己的事情
- Redis只作為存儲引擎
- Proxy的狀態
- Redis故障判定是否放到外部,因為分布式系統存活的判定異常復雜
- 提供API讓外部調用,當Redis Master丟失時,提升Slave為Master
- 圖形化監控一切:slot狀態、Proxy狀態、group狀態、lock、action等等
而在考量了一切事情后,另一個爭論擺在了眼前——Proxy或者是Smart Client:Proxy擁有更好的監控和控制,同時其后端信息亦不易暴露,易于升級;而Smart Client擁有更好的性能,及更低的延時,但是升級起來卻比較麻煩。對比種種優劣,他們最終選擇了Proxy,無獨有偶,在codis開源后,twitter的一個分享提到他們也是基于proxy的設計。
Codis主要包含Codis Proxy(codis-proxy)、Codis Manager(codis-config)、Codis Redis(codis-server)和ZooKeeper四大組件,每個部分都可動態擴容。
codis-proxy 。客戶端連接的Redis代理服務,本身實現了Redis協議,表現很像原生的Redis (就像 Twemproxy)。一個業務可以部署多個 codis-proxy,其本身是無狀態的。
codis-config。Codis 的管理工具,支持添加/刪除Redis節點、添加/刪除Proxy節點、發起數據遷移等操作。codis-config自帶了一個http server,會啟動一個dashboard,用戶可以在瀏覽器上觀察 Codis 集群的運行狀態。
codis-server。Codis 項目維護的一個Redis分支,加入了slot的支持和原子的數據遷移指令。
ZooKeeper。Codis依賴ZooKeeper來存放數據路由表和codis-proxy節點的元信息,codis-config發起的命令會通過 ZooKeeper同步到各個存活的codis-proxy。
最后,劉奇還介紹詳細的了Codis中Migration、lock (rwlock)等操作的實現過程和原理,以及從Twemproxy遷移到Codis的詳細操作。更多Codis詳情可移步Clodis開源頁 GitHub
文章列表