envoy 必须启用 envoy.filters.network.redis_proxy 过滤器才能原生解析 redis 协议并实现 cluster 拓扑感知,因其深度介入 resp 协议层,完成 cluster slots 获取、slot 映射构建、key 哈希路由、跨 slot 请求拆分等关键逻辑;普通 tcp 代理无法识别协议,仅直通转发。

Envoy 能原生解析 Redis 协议并完成 Cluster 拓扑感知,但前提是必须用 envoy.filters.network.redis_proxy 过滤器,且集群配置类型必须为 redis_cluster —— 普通 static 或 strict_dns 集群无法触发 slot 路由逻辑。
为什么 redis_proxy filter 是硬性前提
Envoy 对 Redis 的支持不是靠通用 TCP 代理实现的,而是通过专用网络过滤器深度介入协议层。只有启用 envoy.filters.network.redis_proxy,才能:
- 在连接建立后自动识别 Redis 协议握手(如
RESP格式解析) - 拦截并重写
CLUSTER SLOTS、CLUSTER NODES等管理命令,用于构建本地 slot 映射表 - 对客户端发来的任意 key 命令(如
GET user:1001)计算CRC16(key) % 16384,再查 slot → node 映射,转发到对应后端 - 将多个
MGET或DEL中跨 slot 的 key 拆成多个请求,分别路由(即 transparent sharding)
若只配了普通 TCP filter(如 envoy.filters.network.tcp_proxy),Envoy 完全不理解 Redis 协议,只会做直通代理,无法做 slot 路由、读写分离或命令改写。
redis_cluster 类型集群如何生成 slot 映射
Envoy 不依赖客户端提供集群拓扑,而是主动向任一节点发起 CLUSTER SLOTS 请求,并缓存响应结果。关键行为包括:
- 初始化时,从
load_assignment.endpoints列表中随机选一个节点,发送CLUSTER SLOTS - 响应必须是标准格式:每行包含
start_slot end_slot master_ip:port [replica_ip:port...] - 解析后构建
slot_array_[16384],每个 slot 存指向该节点的Host引用 - 后续定期(默认 60s)重拉
CLUSTER SLOTS,检测拓扑变更;若失败,会尝试换节点重试
常见坑:CLUSTER SLOTS 返回空或格式错误(比如节点未完全握手、防火墙拦截响应),会导致 Envoy 认为“无可用 slot”,所有请求返回 MOVED 或直接失败。可通过 admin /stats?filter=redis 查看 redis.upstream_rq_503 和 redis.cluster_slots_fetch_failed 指标确认。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
读写分离与命令拦截的实际控制点
Envoy 的 Redis 流量治理能力集中在两个地方:一是 redis_proxy 的 settings,二是 typed_extension_protocol_options 下的扩展配置。典型可控项有:
-
op_timeout:单条命令超时(非连接超时),影响GET/SET等操作,但不影响CLUSTER SLOTS自动刷新周期 -
auth_password(在typed_extension_protocol_options.envoy.redis_proxy中):Envoy 代客户端向后端发送AUTH命令,避免客户端暴露密码 -
prefix_routes+catch_all_route:目前仅支持兜底路由;Envoy 不支持按 key pattern 做路由(如user:* → slave),需靠上游 client 或额外 Wasm filter 实现 - 读写分离只能靠部署结构实现:把
redis_cluster配置中的endpoints列表里只填 slave 节点 IP,则所有流量都打到从库;主库需另起一个 cluster 专供写入
注意:redis_proxy 不支持 READONLY 命令自动降级,也不会把 GET 转发到 slave、SET 转发到 master —— 这些必须由你显式拆成两个 cluster 并在上层路由中区分。
性能与调试必须关注的三个指标
Envoy 的 Redis 代理不是“开箱即用就稳”,尤其在高并发 key 查询场景下,以下三项指标最能暴露问题:
-
redis.downstream_cx_destroy_with_active_rq:代表客户端连接断开时仍有未完成请求,说明 op_timeout 设置过短或后端响应慢 -
redis.upstream_rq_time直方图:观察 P99 是否远高于预期(如 >50ms),可能因 slot 映射未 warm up 或某节点网络抖动 -
redis.cluster_slots_fetch_successvsredis.cluster_slots_fetch_failed:比值持续低于 0.95,说明集群拓扑同步不稳定,应检查节点间ping/pong是否通畅、cluster-node-timeout是否设得过大
真正容易被忽略的是:Envoy 的 slot 映射是**进程内全局共享**的,但不会自动 fallback 到其他节点重试 slot 查询失败 —— 它会直接拒绝请求。这意味着,哪怕只有一个 Redis 节点失联导致 CLUSTER SLOTS 获取失败,整个 Envoy 实例的 Redis 流量都会中断,除非你配了多个备用 discovery endpoint 并开启重试逻辑(这需要自定义 CDS 或 EDS 实现)。










