✅为什么Lua脚本可以保证原子性?
原子性在并发编程中,和在数据库中是两种不同的概念。
在数据库中,事务的ACID中原子性指的是"要么都执行要么都回滚"。在并发编程中,原子性指的是"操作不可拆分、不被中断"。
Redis既是一个数据库,又是一个支持并发编程的系统,所以,他的原子性有两种。所以,我们需要明确清楚,在问"Lua脚本保证Redis原子性"的时候,指的到底是哪个原子性。
Lua脚本可以保证原子性,因为Redis是单线程执行命令的,当客户端提交一个Lua脚本的时候,Redis会把他当做一个命令来执行,在这个脚本执行期间,不会有其他的命令插入进来执行。
这样就可以保证整个脚本是作为一个整体执行的,中间不会被其他命令插入。但是,如果命令执行过程中命令产生错误,事务是不会回滚的,将会影响后续命令的执行。
也就是说,Redis保证以原子方式执行Lua脚本,但是不保证脚本中所有操作要么都执行或者都回滚。
那就意味着,Redis中Lua脚本的执行,可以保证并发编程中不可拆分、不被中断的这个原子性,但是没有保证数据库ACID中要么都执行要么都回滚的这个原子性。
扩展知识
什么是Lua
Lua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。它提供了非常易于使用的语法,大量的库,以及可移植性,可以用于开发各种各样的应用。Lua是一种高效、轻便、可扩展的脚本语言。它具有语法简洁、操作易学,支持数据结构定义,支持函数式编程,支持面向对象编程,在功能上可以完全取代Shell、Perl,而在轻便性和可扩展性上又具有极大的优势。
Lua脚本语言的优点:
- 高效性:Lua脚本语言的解释器能够高效的执行脚本,它运行快速,可以实现复杂的程序功能。
- 简单性:Lua脚本语言是一种小巧的编程语言,它只有一小部分的内部机制,易于学习,用代码就可以轻松实现复杂程序功能。
- 可移植性:Lua脚本语言可以在多种操作系统上运行,写好的脚本只要移植到其它系统上就可以运行,可以在不同操作系统上使用,可以节省时间和成本。
- 灵活性:Lua脚本语言具有高度的灵活性,可以实现高效灵活的软件架构,帮助开发者更加精准的实现复杂的需求。
5.安全性:Lua脚本语言的安全性良好,可以保护开发者的代码不受恶意的攻击和恶意的破坏。
以下就是一个Lua脚本,它实现的功能就是转账,通过lua脚本来保证原子性:
-- 转账操作的Lua脚本(支持指定双方账号)
local from_account = KEYS[1]
local to_account = KEYS[2]
local amount_to_transfer = tonumber(ARGV[1])
-- 检查是否有足够的金额可以转账
local from_balance = tonumber(redis.call("GET", from_account))
if from_balance and from_balance >= amount_to_transfer then
-- 执行扣除金额和增加金额的操作
redis.call("DECRBY", from_account, amount_to_transfer)
redis.call("INCRBY", to_account, amount_to_transfer)
return true
else
return false
end例如,如果要从account:123转账给account:456,可以这样调用脚本:
EVAL "脚本内容" 2 account:123 account:456 100