1.如何实现redis 原子性?

3.方案二的具体细节问答

Redis 提供了两种主要机制来保证原子性:

  1. Lua 脚本(推荐方式):

    • 原理: Redis 会将整个 Lua 脚本作为一个整体执行,中间不会被其他命令插入。

    • 优势: 这是目前实现复杂逻辑原子性的最成熟方案(例如实现分布式锁的核心逻辑)。

    • 注意: 脚本执行时间不能过长,否则会阻塞主线程。

  2. 事务 (MULTI / EXEC):

    • 原理: 使用 MULTI 开启事务,将命令入队,最后用 EXEC 一次性执行。

    • 致命缺陷(面试必问): Redis 事务不支持回滚(Rollback)

      • 如果事务中有语法错误(编译时错误),整个事务会被放弃。

      • 但如果事务中有运行时错误(比如对 String 类型做 List 操作),出错的命令会失败,但其他命令依然会成功执行

    • 结论: 它是“伪事务”,无法保证 ACID 中的 A(原子性 - 要么全做要么全不做),因此在现代开发中不如 Lua 脚本常用。

一句话总结: “简单逻辑用单条命令(本身原子),复杂逻辑用Lua 脚本(确保整体原子),尽量少用事务(因为不支持回滚)。”

2.除了lua有没有什么也能保证redis的原子性?

有,主要包含以下 2 种方案(重点是 Redis 7.0 新特性):

  1. Redis Functions (Redis 7.0+ 新特性):

    • 定义: 这可以理解为 Lua 脚本的“进化版”。它将脚本逻辑持久化存储在 Redis 服务端,不再需要每次都从客户端发送脚本代码。

    • 优势: 像调用 SQL 存储过程一样调用它(使用 FCALL 命令),不仅节省了带宽,还解决了 Lua 脚本丢失或管理混乱的问题,同样严格保证原子性

  2. 单条命令 (Native Commands):

    • 原理: Redis 的核心命令处理是单线程的,所以任何单条核心命令(如 INCR, DECR, SETNX, MSET)本身就是绝对原子的。

    • 应用: 对于简单的计数或状态切换,直接用单条命令即可,不需要搞复杂的脚本。

补充说明(面试防坑): “虽然 事务 (MULTI/EXEC) 也可以打包执行命令,但因为它不支持回滚(报错后继续执行后续命令),所以在严格要求原子性的复杂业务场景下(如转账),通常不推荐作为首选方案,而是优先使用 Lua 脚本Redis Functions。”