go中redis的watch+multi不是acid事务,而是需手动重试的乐观锁;txpipeline仅为批量发包优化,无原子性;高一致性场景应优先用lua脚本或应用层分布式锁。

Redis 的 WATCH + MULTI 在 Go 中不等于“事务”
Go 官方 redis 客户端(github.com/go-redis/redis/v9)根本不支持传统 Redis 的 MULTI/EXEC 事务语义——它不会阻塞、不保证原子性、也不回滚失败命令。所谓“事务”,在 Go 里实际是靠 WATCH 配合重试模拟的乐观锁,不是数据库那种 ACID 事务。
常见错误现象:EXEC 返回空结果、中间某条命令报错但其余仍执行、并发写入时数据被覆盖却无感知。
-
WATCH必须在GET或读操作前调用,且只对 key 生效;watch 后若 key 被其他客户端修改,EXEC会返回nil - 整个流程需手动包裹 for 循环 + 重试逻辑,没有自动机制
- 不推荐用于高冲突场景(比如秒杀),重试开销大,容易雪崩
TxPipeline 不是事务,是批量发包优化
TxPipeline 是 go-redis 提供的批量命令发送方式,底层把多条命令打包成一次 TCP 包发出,减少 RTT,但它完全不提供原子性或隔离性——每条命令独立执行、独立返回、独立可能失败。
使用场景:你只是想“一口气发 10 条 SET”,又不想写 10 次 client.Set() 网络调用,且能接受部分成功部分失败。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 调用
client.TxPipeline()后,所有命令都暂存内存,直到调用exec := pipeline.Exec(ctx) -
exec返回[]interface{}和error;即使某条命令失败(如INCR对 string 类型 key),其余命令照常执行,错误只体现在对应位置的interface{}是*redis.StatusError - 注意:pipeline 不跨 slot(集群模式下),如果命令涉及多个 slot 会 panic,必须提前确认 key 分布或改用
client.Pipeline()(非事务型)
真正需要原子写入?用 Lua 脚本替代
Redis 原生保证 Lua 脚本的原子执行(单个 Redis 实例内),这是 Go 中最可靠、最轻量的“事务替代方案”。go-redis 通过 script.Load() + script.Eval() 支持。
典型例子:扣减库存并记录日志,两个操作必须一起成功或一起失败。
const luaScript = `
if redis.call("GET", KEYS[1]) >= ARGV[1] then
redis.call("DECRBY", KEYS[1], ARGV[1])
redis.call("LPUSH", KEYS[2], ARGV[2])
return 1
else
return 0
end
`
script := redis.NewScript(luaScript)
result, err := script.Eval(ctx, client, []string{"inventory:123", "log:123"}, "5", "order_abc").Int()
- Lua 脚本中不能调用带随机性或时间依赖的命令(如
TIME、RANDOMKEY),否则集群模式下无法路由 - 脚本长度建议控制在 1KB 内,过长影响性能且难以调试
- 务必用
script.EvalSha复用已加载脚本,避免每次传输源码
集群模式下 WATCH 和 TxPipeline 都受限
Redis Cluster 要求所有 multi-key 操作的 key 必须落在同一个 slot,而 WATCH 多 key、TxPipeline 多 key 命令若 hash tag 不一致,会直接报错 CROSSSLOT Keys in request don't hash to the same slot。
- 解决办法只有两个:1)所有 key 强制同 slot,例如用
{user:123}:balance和{user:123}:seq;2)退化为单节点 Redis 或用 Redis Proxy(如 Codis) - 别指望
client.ClusterClient自动帮你拆分 pipeline——它不会,也不会重试 watch 失败 - 集群下 Lua 脚本也受 slot 限制,
EVAL必须所有 KEYS 在同一 slot,否则报错
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










