原子性在并发编程中,和在数据库中是两种不同的概念。
在数据库中,事务的 ACID 中原子性指的是 “要么都执行要么都回滚”。在并发编程中,原子性指的是 “操作不可拆分、不被中断”。
Redis 既是一个数据库,又是一个支持并发编程的系统,所以,它的原子性有两种。所以,我们需要明确清楚,在问 “Lua 脚本保证 Redis 原子性” 的时候,指的到底是哪个原子性。
Lua 脚本可以保证原子性,因为 Redis 是单线程执行命令的,当客户端提交一个 Lua 脚本的时候,Redis 会把他当做一个命令来执行,在这个脚本执行期间,不会有其他的命令插入进来执行。
这样就可以保证整个脚本是作为一个整体执行的,中间不会被其他命令插入。但是,如果命令执行过程中命令产生错误,事务是不会回滚的,将会影响后续命令的执行。
也就是说,Redis 保证以原子方式执行 Lua 脚本,但是不保证脚本中所有操作要么都执行或者都回滚。
那就意味着,Redis 中 Lua 脚本的执行,可以保证并发编程中不可拆分、不被中断的这个原子性,但是没有保证数据库 ACID 中要么都执行要么都回滚的这个原子性。