必须用redis.newclusterclient而非redis.newclient,因后者不处理moved/ask重定向、不解析cluster slots、不执行crc16 slot映射,导致请求打错节点后直接报错;正确方式是传*redis.clusteroptions,addrs至少填2–3个可连通主节点地址,并确保节点间端口互通。

必须用 redis.NewClusterClient,不是 redis.NewClient
很多刚接触 Redis 集群的 Go 开发者会照着单机示例写 redis.NewClient,结果能连上、能 SET/GET,但一跑批量操作或换 key 就出错——因为客户端根本没走集群路由逻辑,所有请求都被打到第一个节点,遇到跨 slot 命令(比如 KEYS *)直接报 CROSSSLOT Keys in request don't hash to the same slot。
真正生效的初始化方式只有一种:redis.NewClusterClient,且必须传 *redis.ClusterOptions。它内部依赖 CLUSTER SLOTS 响应构建本地 slot 映射表,这是集群模式运转的前提。
- 别在配置里混用单机和集群字段:例如
Addr和Addrs不能同时设,Addr是单机用的,Addrs才是集群用的切片 -
redis.NewClient连集群地址会静默降级为单节点通信,不报错也不提示,排查时容易误判 - 如果项目要兼容单机/集群两种模式,得在代码里分支判断,而不是靠“同一个 client 自动适配”
Addrs 至少填 2–3 个可连通的主节点地址
集群客户端不会轮询 Addrs 列表里的地址去试连——它只取第一个成功响应 CLUSTER SLOTS 的节点,然后从它的返回里提取全部 master 地址。如果第一个地址不可达,整个初始化就卡住或超时失败。
所以 Addrs 不是“备用地址”,而是“初始发现入口”。实操中必须保证列表里至少有 2–3 个状态正常的 master 节点地址,且它们都处于 connected 状态(用 redis-cli -c CLUSTER NODES 确认)。
- Docker 环境别写
localhost:7000,改用host.docker.internal:7000或服务名(如redis-node-1:7000) - 地址必须带端口,
127.0.0.1:7000和127.0.0.1:7001是两个独立入口,缺一不可 - 不要往
Addrs里塞从节点地址,除非你明确启用了ReadOnly模式;否则初始化阶段连从节点可能因不响应CLUSTER SLOTS导致超时
连接池大小和 Ping() 验证不能省略
默认 PoolSize: 10 在测试环境够用,但上线后 QPS 上千时,连接池很快耗尽,出现 redis: connection pool timeout。更隐蔽的问题是:不主动 Ping(),第一次 Get() 失败才暴露配置错误,线上服务已启动却无法缓存。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
初始化阶段必须做两件事:设合理 PoolSize,并用带超时的 context 主动探测。
-
PoolSize建议设为runtime.NumCPU() * 5起步,再按预估并发请求数调整(例如 200 QPS → 设 40–80) - 务必调
rdb.Ping(ctx).Err(),ctx 要带WithTimeout(3 * time.Second),别用context.Background() - 进程退出前调
rdb.Close(),否则 fd 泄漏,最终触发too many open files
集群模式下哪些命令不能用
Redis 集群强制要求 key 必须落在同一 slot,所以所有可能跨 slot 的命令都被禁用。这不是客户端限制,是集群协议层拦截,Go 客户端收到的是明确错误,不是超时或空响应。
常见被拒命令及其替代方案:
-
KEYS *→ 改用SCAN,但注意游标必须指定具体节点(先CLUSTER KEYSLOT key算出 slot,再连对应节点执行) -
SCAN默认游标为 0 时可能触发跨 slot 请求 → 必须配合redis.WithArgs("MATCH", pattern, "COUNT", 100)显式控制范围 -
MGET多 key → 所有 key 必须属于同一 slot,否则报CROSSSLOT;可提前用redis.CalcSlot(key)校验 -
FLUSHDB/FLUSHALL→ 集群不支持,需遍历每个 master 节点单独执行
最常被忽略的是:结构体序列化必须字段导出+json tag,否则 json.Unmarshal 返回空对象;time.Time 建议转 int64 存,避免 JSON 时间格式歧义。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










