Rust 寫的 Undermoon Redis 集群 -Redis Cluster Protocol與Server Proxy
感謝 doyoubi 提供這么好的項目,原文:https://github.com/doyoubi/undermoon/blob/master/docs/redis_cluster_protocol.md
Redis Cluster 是官方的 Redis 分布式解決方案,支持 sharding(分片) 和 failover(故障轉移)。與使用單實例 redis 相比,連接 Redis Cluster 的客戶端需要實現 Redis Cluster Client Protocol。它的基本作用是:
- 如果我們沒有向正確的節點發送命令,則重定向請求。
- 從 CLUSTER NODES 和 CLUSTER SLOTS 這兩個命令之一緩存集群路由表。
這種客戶端稱為 Smart Client。
https://redis.io/topics/cluster-tutorial
為了兼容現有的 Redis client,還有一些 Redis Cluster Proxies,如 redis-cluster-proxy(官方)、aster、corvus 和 samaritan,以使集群協議適應廣泛支持的單實例協議。
- https://github.com/RedisLabs/redis-cluster-proxy
- https://github.com/wayslog/aster
- https://github.com/eleme/corvus
- https://github.com/samaritan-proxy/samaritan
Undermoon 是如何實現 “Redis Cluster Protocol” 的?
Undermoon 基于 server-side proxy 或 Server Proxy 實現 Redis Cluster Protocol。Server Proxy 將像官方的 Redis Cluster Redis 一樣工作,并在需要時返回重定向響應。
為什么要實現另一個 “Redis Cluster Protocol”?
該實現不僅支持水平可擴展性和高可用性,還使您能夠構建一個自我管理的分布式 Redis,支持:
- Redis 資源池管理
- 為不同的用戶提供多個集群
- 將流量洪水均勻地傳播到所有物理機
- 擴容迅速
- 操作和 Kubernetes 集成更容易。
為什么是 Server-side Proxy?
Redis 和大多數 redis 代理(如 redis-cluster-proxy、corvus、aster、codis)部署在獨立的機器上,因為代理通常需要將請求分散到不同的 Redis 實例。
Server-side Proxy 不是路由請求,而是充當與這些代理不同的角色,類似于 Redis 的 cluster module,通過使用一些定制的遷移協議,使其能夠遷移數據并快速擴展。
Server-side Proxy
以下是 Server-side Proxy 和 Redis Cluster Protocol 的一小部分操作。
首先運行一個 redis-server。
$ redis-server
構建并運行 server_proxy,在端口 5299 上運行并將命令轉發到 127.0.0.1:6379。
> cargo build
> make server
> redis-cli -p 5299
# 通過 `UMCTL` 命令初始化代理。
127.0.0.1:5299> UMCTL SETCLUSTER v2 1 NOFLAGS mydb 127.0.0.1:6379 1 0-8000 PEER 127.0.0.1:7000 1 8001-16383
# Done! 我們可以像 Redis Cluster 一樣使用它!
# 和官方的 Redis Cluster 不同,這里只顯示 master 節點
# 而不是同時顯示主服務器和副本。
127.0.0.1:5299> CLUSTER NODES
mydb________________9f8fca2805923328____ 127.0.0.1:5299 myself,master - 0 0 1 connected 0-8000
mydb________________d458dd9b55cc9ad9____ 127.0.0.1:7000 master - 0 0 1 connected 8001-16383
# 當我們使用 UMCTL SETCLUSTER 初始化它時,
# 插槽(slots) 8001-16383 屬于另一個服務器代理 127.0.0.1:7000
# 所以我們得到一個重定向響應。
#
# 這是普通 Redis client 和 Redis Cluster client 的關鍵區別
# 因為我們需要處理重定向。
127.0.0.1:5299> get a
(error) MOVED 15495 127.0.0.1:7000
# Key 'b' 是該代理負責的,因此我們處理請求。
127.0.0.1:5299> set b 1
OK