这是 Beta 探索课程,内容结构、实验步骤和示例可能会继续调整。
Lua 脚本
原子性问题
在使用 Redis 时,我发现了一个棘手的问题。
问题在哪里?
场景:用户快速点击两次点赞
时间线:
T1: 线程 A 检查 → 未点赞
T2: 线程 B 检查 → 未点赞(同时)
T3: 线程 A 添加点赞 → 成功
T4: 线程 B 添加点赞 → 成功(重复!)
T5: 线程 A 计数 +1 → 101
T6: 线程 B 计数 +1 → 102
结果:
- 点赞集合:用户 ID 重复
- 计数:102(应该是 101)
→ 数据不一致!
原因:三个操作不是原子的。
解决方案:Lua 脚本。
Lua 脚本原理
什么是 Lua 脚本?
Lua 脚本:
- Redis 支持的脚本语言
- 在 Redis 服务器端执行
- 保证原子性
- 减少网络往返
为什么能保证原子性?
Redis 执行 Lua 脚本的过程:
1. 客户端发送 Lua 脚本
2. Redis 解析脚本
3. Redis 执行脚本(单线程,不会被打断)
4. 返回结果
关键点:
- Redis 是单线程的
- 执行 Lua 脚本时,其他命令等待
- 整个脚本是一个原子操作
示意图:
不使用 Lua 脚本:
客户端 → Redis: SISMEMBER → 客户端 → Redis: SADD → 客户端 → Redis: INCR
↑____________↑____________________↑
3 次网络往返,可能被其他请求打断
使用 Lua 脚本:
客户端 → Redis: 执行整个脚本 → 返回结果
↑________________________↑
1 次网络往返,原子执行
基础用法
点赞操作
取消点赞
高级用法
批量操作
条件更新
复杂业务逻辑
性能优化
脚本缓存
性能对比
注意事项
脚本超时
脚本调试
实际应用
点赞 + 限流
课后练习
练习 1
Lua 脚本如何保证原子性?
参考答案(3 个标签)
Lua原子性Redis
Redis 单线程模型:
Redis 执行命令的顺序:
1. 客户端 A 发送命令
2. Redis 执行命令
3. 客户端 B 发送命令
4. Redis 执行命令
5. ...
关键点:
- Redis 是单线程的
- 命令按顺序执行
- 一个命令执行期间,其他命令等待
Lua 脚本:
- 整个脚本作为一个命令
- 执行期间不会被其他命令打断
- 保证原子性练习 2
Lua 脚本如何处理错误?
参考答案(3 个标签)
Lua错误处理调试
错误处理方案:
原子操作要点
- 这里关注的是把读取、判断和更新合成一个不可打断的状态变化,而不是记住脚本语法。
练习 3
如何优化 Lua 脚本的性能?
参考答案(3 个标签)
Lua性能优化最佳实践
优化技巧:
原子操作要点
- 这里关注的是把读取、判断和更新合成一个不可打断的状态变化,而不是记住脚本语法。
练习 4
Lua 脚本如何访问全局变量?
参考答案(3 个标签)
Lua全局变量作用域
全局变量限制:
原子操作要点
- 这里关注的是把读取、判断和更新合成一个不可打断的状态变化,而不是记住脚本语法。
练习 5
如何实现 Lua 脚本的”版本管理”?
参考答案(3 个标签)
Lua版本管理运维
方案:脚本版本化
思考题
-
Lua 脚本能否访问外部资源(如数据库、网络)?
-
如何测试 Lua 脚本的正确性?
-
Lua 脚本和 Redis 事务有什么区别?
💡 提示:这些问题没有标准答案,建议结合实际情况深入思考。
