屏蔽 Redis 的部署模式差异
Redis 可以部署为单机模式或者 Cluster 模式。Cluster 模式相对于单机模式有以下优点:
- 支持水平扩展,可以通过增加节点数量可提高集群的性能和容量。
- 支持自动分区,可以将数据分散到不同的节点上,提高负载均衡和可用性。
- 具备一定的容错能力,即使某个节点宕机或网络出现问题,也可以自动进行故障转移和恢复。
Redis 要求分别采用不同的 client API 访问单机模式和 Cluster 模式。通过采用 Aeraki Mesh 的 Redis 流量管理功能,我们可以在不修改客户端代码的前提下切换后端的 Redis 部署模式,从而降低了应用开发的复杂度。
比如我们可能在测试集群使用一个小型的单实例 Redis ,而在生产环境使用一个包含多个实例的 Redis Cluster。通过 Aeraki Mesh,我们无需修改应用的代码/配置就可以将应用对接到不同环境的 Redis 服务上,从而尽可能的保证了 12-Factor 应用中的开发,预发布,线上环境的一致性,实现应用的持续部署。
Demo 中部署的 Redis Cluster 由 6 台 Redis 服务器组成,Cluster 中有三个分片(Shard),每个分片中有一个 Master 节点,一个 Slave 节点。我们可以通过下面的命令来查看该 Redis Cluster 的拓扑结构:
kubectl exec -it redis-cluster-0 -c redis -n redis -- redis-cli cluster shards
该 Redis Cluster 的拓扑结构如下图所示。从图中可以看到,该 Cluster 有三个分片(Shard)每个 Shard 负责一个范围的槽位(Slot),Shard 0 负责处理 Slot 0 到 5460,Shard 1 负责处理 Slot 5461 到 10922,Shard 2 负责处理 10923 到 16383。每个 Key 对应的 Slot 是固定的,其计算方式为 CRC16(key) mod 16384
。
当我们向 Redis Cluster 中写入或者读取数据时,要求客户端根据算法 CRC16(key) mod 16384
计算出数据所属的 Slot,然后将数据发送到对应 Shard 中的节点上。
当我们尝试通过 Redis 客户端访问 demo 中部署的 Redis cluster,会出现下面的访问错误:
kubectl exec -it `kubectl get pod -l app=redis-client -n redis -o jsonpath="{.items[0].metadata.name}"` -c redis-client -n redis -- redis-cli -h redis-cluster
redis-cluster:6379> set foo bar
(error) MOVED 15495 10.244.0.23:6379
这是因为 Redis 客户端采用了普通模式的 API。客户端将请求发送到 redis-cluster 服务,然后该请求被随机分发到该服务后端的一个 Redis 节点上。如果该节点不是请求的 key 根据算法算出的 Slot 所在的分片,那么该节点会返回一个 MOVED 错误,告诉客户端应该访问哪个节点。客户端会根据该错误,重新发送请求到正确的节点。但是,由于客户端采用的是普通模式的 API,因此客户端无法解析该错误,也就无法重新发送请求。因此,客户端会一直报错。
通过配置 RdisDestination 中的模式为 CLUSTER,Aeraki Mesh 可以为我们屏蔽 Cluster 模式和独立模式的差异。
kubectl apply -f- <<EOF
apiVersion: redis.aeraki.io/v1alpha1
kind: RedisDestination
metadata:
name: external-redis
namespace: redis
spec:
host: external-redis.redis.svc.cluster.local
trafficPolicy:
connectionPool:
redis:
mode: CLUSTER
EOF
此时我们就可以像访问一个独立 Redis 节点一样访问 redis-cluster 服务了。
kubectl exec -it `kubectl get pod -l app=redis-client -n redis -o jsonpath="{.items[0].metadata.name}"` -c redis-client -n redis -- redis-cli -h redis-cluster
redis-cluster:6379> set foo bar
OK
采用该方法,我们可以在开发和生产环境中无缝切换,而无需修改应用代码。我们也可以在应用业务规模逐渐扩张,单一 Redis 节点压力过大时,将系统中的 Redis 从单节点无缝迁移到集群模式。
在集群模式下,不同 key 的数据被缓存在不同的数据分片中,我们可以增加分片中 Replica 节点的数量来对一个分片进行扩容,也可以增加分片个数来对整个集群进行扩展,以应对由于业务不断扩展而增加的数据压力。Aeraki Mesh 通过配置 Envoy 代理了 Redis 的流量,整个迁移和扩容过程对客户端完全透明,不会影响到线上业务的正常运行。
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.