go-redis v8连接Redis哨兵模式时XReadStreams调用报WRONGTYPE错误
问题场景
使用github.com/go-redis/redis/v8客户端读取Redis Streams数据,Redis服务采用Sentinel哨兵模式部署,客户端初始化代码如下:
client := redis.NewFailoverClient(&redis.FailoverOptions{ MasterName: common.RedisSentinalMasterName, SentinelAddrs: sentinalAddr, PoolSize: poolSize, MinIdleConns: idleConns, MaxRetries: 3, DB: 1, ReadTimeout: 15 * time.Minute, WriteTimeout: 15 * time.Minute, })
流读取调用代码:
result, err := client.XReadStreams(ctx, streamName, id).Result()
调用持续返回错误:
WRONGTYPE Operation against a key holding the wrong kind of value
完全相同的业务代码连接单机部署的Redis服务时可正常运行,无该报错。
根本原因
WRONGTYPE错误的核心触发逻辑是:执行命令要求的数据类型,和目标key实际存储的数据类型不匹配。XReadStreams仅能对Stream类型的key执行,哨兵模式下报错、单机正常,基本都是以下原因导致:
- 客户端连接的Redis实例/DB不符合预期:
MasterName配置错误、SentinelAddrs填错了其他业务的哨兵地址、DB参数和存储Stream数据的库编号不一致,导致客户端实际连接的Redis节点上,目标streamName是其他业务写入的String/Hash/List/ZSet等非Stream类型的同名key。 - 开启了从节点读配置但主从数据不一致:如果配置了
ReadOnly: true让客户端读从节点,当主从同步出现异常、或者从节点上残留了同名旧类型key(比如之前用过同名key存其他类型,没删干净就新建了Stream,主从同步没覆盖旧值),读请求打到从节点时就会触发类型错误。 - 哨兵集群内存在脏数据:和单机环境的干净测试数据不同,哨兵集群的对应DB里可能残留了历史测试写入的同名非Stream key,没有提前清理。
排查&解决步骤
- 先定位客户端实际连接的节点:在业务代码里通过连接池状态拿到当前连接的Redis节点地址,登录该节点执行
SELECT 1切到配置的DB1,再执行TYPE <你的streamName实际值>查看key类型:- 如果返回值不是
stream,直接确认该key是冲突脏数据:确认无用的话直接执行DEL <streamName>删除冲突key即可;如果是其他业务在用的有效key,修改你业务侧的Stream key名称避免重名。 - 如果返回
none说明连错了实例/DB,核对修正MasterName、SentinelAddrs、DB三个配置项,确保客户端连到存储Stream数据的正确集群和库。
- 如果返回值不是
- 如果key类型确认是Stream仍报错,检查是否开启了从节点读:在
FailoverOptions里暂时加上ReadOnly: false强制所有请求走主节点,验证是否是主从数据不一致导致的问题,后续排查修复主从同步异常即可。 - 若以上配置都没问题,升级
go-redis/v8到最新的补丁版本,旧版本存在少量哨兵模式下路由错误的已知bug,会导致请求被打到错误的节点。
内容的提问来源于stack exchange,提问作者Avinash Vundyala
相关产品推荐
相关产品推荐

