← [ BACK_TO_NOTES ]

Redis 原子性、事务与 Lua

解释 Redis 单命令原子性与多步竞态的边界,以及 MULTI/EXEC、WATCH、Lua/Functions 在 read-check-write 和多 Key 状态转换中的职责。

#concept #growing #backend #redis

[!info] related notes

Redis 原子性、事务与 Lua

一句话定义

Redis 的单条命令通常具有原子执行语义,但应用层的多条命令组合并不会自动原子;需要根据状态转换选择更强的单命令、MULTI/EXEC、WATCH 或 Lua / Redis Functions。

危险形状:Read → Check → Write

GET state
→ application decides
→ SET new-state

多个客户端可以交错:

A GET
B GET
A SET
B SET

每条命令都原子,整体仍会发生 lost update 或多赢家竞态。

优先级

1. 优先使用已有原子命令

counter increment       → INCR
create only if absent   → SET ... NX
set membership          → SADD / SREM

不要为了“原子性”把本来已经原子的单命令套进 Lua。

2. MULTI / EXEC

提供一组命令连续执行、不被其他普通客户端命令插入的执行边界。

[!warning] MULTI/EXEC 不等于关系数据库事务;它不是任意执行期错误都自动回滚前面已执行操作的 ACID transaction。

3. WATCH

适合乐观并发控制:

WATCH key
→ read
→ application check
→ MULTI / EXEC

如果 WATCH 之后 Key 被别人修改,事务可失败并由客户端重试。

4. Lua / Redis Functions

适合:

多个 Redis 操作
+ Redis 内部条件判断
+ 必须形成 single-winner 状态转换

整个脚本在 Redis 中原子执行,同时减少多次网络往返。

BodySense 典型场景

Rate Limit

INCR
+
首次请求 EXPIRE

如果分成两次网络操作,中间失败可能留下无 TTL counter;Lua 可把它收敛成一个原子状态转换。

Session 创建 / 撤销

SET session:<sid>
SADD user_sessions:<uid> <sid>

以及对应删除,需要避免应用崩溃造成 authority 与 secondary index 的主动写入不一致。

Refresh Token Rotation

check old token active
→ consume old token
→ write replay tombstone
→ create new token
→ update family

必须保持 single-winner,避免一个旧 Refresh Token 并发分叉出多个合法后代。

Lua 的边界

  • 脚本应短、小、确定;
  • 大循环或重计算会阻塞 Redis 命令处理路径;
  • Lua 只能保护脚本覆盖的主动状态转换;
  • TTL 自动过期不会自动触发应用自定义 Lua 清理关联索引;
  • 跨 PostgreSQL + Redis 的原子性不能由一段 Redis Lua 自动解决。

速查

单条原子操作够用          → 原生命令
连续执行一组命令          → MULTI / EXEC
乐观 read-check-write      → WATCH + MULTI / EXEC
Redis 内部条件 + 多步状态机 → Lua / Redis Functions
创建于 2026/9/18 更新于 2026/9/18
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本