基于Redis的開源分布式服務Codis
原文 http://www.cnblogs.com/shanyou/p/4268896.html
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 開源后, 推ter 的一個分享提到他們也是基于 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