Kubernetes集群中Redis Headless Service作用及读写报错问题咨询
报错根因
你遇到的报错:
2021-11-16T05:32:18 [INFO] - increment delete failed...,MobcError(RedisCMDError(An error was signalled by the server: You can't write against a read only replica.))
本质是当前使用的Redis连接字符串:
redisConnectionStr="redis://default:password@cruise-redis-headless.reddwarf-cache.svc.cluster.local:6379/3"
指向的Headless Service同时绑定了Redis主节点和从节点的Pod,K8s对Headless Service的DNS解析会直接返回所有关联Pod的IP列表,普通单连接客户端会随机选一个IP建立连接,当选中只读从节点时,写操作自然会被拒绝。
Redis Headless Service的适用场景
- 有状态集群内部组网:Redis配合StatefulSet部署时,Headless Service会为每个Redis Pod生成固定的DNS域名(格式为
{Pod名}.{Headless Service名}.{命名空间}.svc.cluster.local),方便Redis节点之间完成主从同步、哨兵选举、集群槽位同步等内部交互,不需要依赖动态IP寻址。 - 客户端侧服务发现:当使用Redis哨兵模式、Redis Cluster模式时,客户端需要感知全量Redis节点的IP、角色信息来实现自定义路由、读写分离、故障转移逻辑,Headless Service可以通过一次DNS查询返回所有节点IP,不需要调用K8s API拉取Pod列表。
- 自定义流量调度:如果业务需要实现更灵活的负载策略(比如就近访问、按节点负载分配请求、自定义读写分流规则),可以通过Headless Service获取全量节点地址,在客户端侧实现调度逻辑,不受K8s Service默认的轮询负载策略限制。
为什么不直接使用独立的主节点Service+从节点Service方案
拆分主、从独立Service是轻量、小规模Redis主从架构下的首选方案,实现简单,业务侧只需要把写请求发往主节点Service、读请求发往从节点Service即可,不需要做额外的客户端改造,但该方案存在明显的局限性:
- 主从切换适配成本高:当Redis发生主从切换后,主节点Service的标签选择器必须同步更新才能指向新的主节点,否则写请求会被发到已经降级为从节点的旧主节点,触发写失败,额外依赖自动化运维组件支持。
- 不支持高级集群模式:Redis Cluster模式下没有固定的全局主从角色,每个节点都可能负责部分哈希槽的读写,拆分主从Service完全没有意义,必须通过Headless Service让客户端感知全量节点自行路由。
- 运维复杂度高:Redis集群扩容、缩容从节点时,都需要同步调整从节点Service的标签选择器,集群规模越大运维成本越高。
需要使用Redis Headless Service的场景
符合以下任意条件时,建议使用Headless Service部署Redis:
- 部署的是哨兵模式、Redis Cluster模式的集群,需要客户端自行实现节点发现、请求路由
- 依赖StatefulSet部署Redis,需要为每个节点提供固定的可解析域名用于内部通信
- 业务侧有自定义的读写分离、流量调度需求,不希望受K8s Service默认负载规则限制
- 使用开源Redis Operator部署集群,绝大多数主流Redis Operator都会默认创建Headless Service用于集群管理
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

