Go语言Redis怎么做分布式锁_Go语言Redis分布式锁教程【基础】
Redis的SETNX命令只接受key和value两个参数,若用Do方法多传参数(如EX),会导致协议解析失败而返回nil;应改用SET命令的NX+EX选项或go-redis/v9的SetNX方法。redis.Client.Do 调用 SETNX 为什么总是返回 nil?Go 用 redis.Client.Do 直接发 SETNX 命令,结果拿到 nil,不是 1 或 0 —— 这大概率是命令参数传错了。Redis 的 SETNX 只接受两个参数:key 和 value,但 Go 的 Do 方法会把每个参数单独序列化,如果你写了 c.Do("SETNX", "mylock", "abc", "EX", "10"),Redis 实际收到的是 5 个参数,它不认识 EX,直接忽略后续,只执行 SETNX mylock abc,然后返回 1 或 0;但如果你多传了(比如误加了 nil 或空字符串),底层协议解析失败,就可能返回 nil。更稳妥的做法是改用 SETEX 或(推荐)SET 命令的原子选项:c.Do("SET", "mylock", "abc", "NX", "EX", "10") —— 注意顺序:NX 和 EX 是 flag,不是值,必须紧挨在 value 后面用官方 github.com/go-redis/redis/v9 的 SetNX 方法,自动处理类型和错误,返回 bool, error别自己拼 Do,除非你明确需要绕过 client 封装做特殊协议操作用 redigo 还是 go-redis/v9?锁超时后自动续期怎么做?选 go-redis/v9。redigo 是低层封装,所有命令都要自己处理连接、重试、类型转换;而分布式锁的核心难点不在“设个 key”,而在“持有期间续期”和“释放时校验所有权”。v9 提供 Lock / Unlock 接口,背后用 Lua 脚本保证删除操作的原子性(只删自己设的 value),redigo 没这层能力,得自己写脚本、自己 EVAL、自己比对 value,极易出错。自动续期(renew)不是开个 goroutine 定时 EXPIRE —— 那不原子,且无法判断锁是否已被别人抢走。正确做法是:立即学习“go语言免费学习笔记(深入)”;初始化锁时传入 WithContext + WithExpiration,并启用 WithAutoRefresh锁对象内部起一个 ticker,在剩余 TTL 的 1/3 时间点尝试刷新(需服务端支持,v9 默认开启)刷新失败(比如锁已丢失)会触发回调,你可以选择 panic 或降级逻辑注意:auto-refresh 不是无限续,它只在锁仍被当前客户端持有时才生效解锁时报 “ERR no such key” 或 “attempt to unlock unlocked mutex”这不是 Redis 报错,是客户端库(如 go-redis/v9 的 mutex 包)抛的 panic。根本原因是:你调用了 Unlock,但此时 key 已过期、被别的客户端覆盖、或压根没成功加锁(比如 SetNX 返回 false 却没检查)。 AI智研社 AI智研社是一个专注于人工智能领域的综合性平台
