回答
Lua
脚本能够保证原子的原因在于 Redis 是采用单线程执行命令的,而当 Redis 在执行一个 Lua
脚本的时候,它会将整个脚本作为一个单独的、不可分割的整体执行。这意味着一旦 Redis 执行某个 Lua
脚本,它就会执行该 Lua
脚本中的所有命令,且不允许在这个中间执行其他命令。
需要注意的是,这里的原子性与 ACID 中的原子性是有区别的,ACID 中的原子性需要保证“要么都执行要么都回滚”,而这里的原子性指的是 Redis 保证以原子方式执行 Lua
脚本,但是不保证 Lua
脚本中的所有操作要么都执行要么都回滚。
扩展
什么是 Lua 脚本
Lua
是一种高效的、轻量级的、可嵌入的脚本语言,用标准C语言编写并以源代码形式开放。其主要目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。
由于其简洁的语法、灵活的语言特性以及高性能的实现,Lua
被广泛用于各种应用场景中,从游戏开发到嵌入式系统,再到服务器应用程序,尤其在需要一个可嵌入、高度可定制的脚本解决方案的场合。
其核心特征有:
- 轻量级:
Lua
追求简洁,核心解释器易于嵌入到其他应用程序中,对资源的消耗非常低。 - 高效:
Lua
使用一种字节码解释器,通过即时编译技术,可以获得接近原生代码的执行速度。 - 可移植:
Lua
可以在几乎所有的操作系统上面运行,写好的脚本只需要移植的其他操作系统就可以执行。 - 可扩展:提供了丰富的 API,允许深度嵌入到应用程序中。
Redis 为什么要引入 Lua 脚本
Redis 提供了丰富的指令集,可以满足绝大多数场景,但是有些特定的场景,是单个命令无法实现的,为了实现更复杂的场景,Redis 2.6 引入 Lua 脚本。
在 Redis 中使用 Lua
脚本有如下几个好处:
- 减少网络开销:将多个命令封装在一个
Lua
脚本中,只需一次即可完成所有的命令执行,大大减少了网络开销。 - 原子性操作:
Lua
脚本保证脚本内的所有操作都是原子性执行的,即脚本执行过程中不会被其他命令中断。 复用性:
客户端发送的Lua
脚本会永远存储在Redis
中,意味着其他客户端可以复用这一脚本