01-Redis Lua
基本操作
Redis 中执行 Lua 可以通过两种方式:
- eval:将 Lua 脚本或命令直接使用 Redis 执行,
- evalsha:把脚本或命令保存到 Redis 中,然后使用一串 sha 码调用(可以理解为调用函数)
在Redis使用LUA脚本的好处包括:
减少网络开销,在 Lua 脚本中可以把多个命令放在同一个脚本中运行;
原子操作,Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。换句话说,编写脚本的过程中无需担心会出现竞态条件;
- ACID的原子性是指:事务中的命令要么全执行,要么全部不执行;
- Redis 中执行 Lua 脚本原子性是指:Lua脚 本会作为一个整体执行且不被其他客户端打断,至于 Lua 脚本里面的命令是否必须全部成功,或者全部失败,并不要求。
复用性,客户端发送的脚本会存储在Redis中,这意味着其他客户端可以复用这一脚本来完成同样的逻辑
eval
语法:
1 |
|
例子(在 Redis 中执行):
1 |
|
输出:
1 |
|
这里传入的key个数为1,所以 Redis 是key而world是参数
使用 redis-cli 执行。
1 |
|
evalsha
这个操作相当于把脚本加载到 Redis ,得到一个 SHA1 的校验和,然后使用这个 SHA1 码来调用对应的 Lua 脚本,避免每次去发送Lua 脚本。
加载脚本
1 |
|
例子:
1 |
|
使用
执行 evalsha
1 |
|
如:
1 |
|
Redis 管理脚本的方式
Redis 提供了几个命令来管理脚本
- script load
- script exists
- script flush
- script kill
script load
用于将 Lua 脚本加载到 Redis 内存中
1 |
|
script exists
用于判断 sha1 值是否已经加载到 Redis 内存中
1 |
|
返回个数
script flush
用于清除 Redis 内存已经加载的所有脚本
1 |
|
script kill
用于杀掉正在执行的Lua脚本
1 |
|
如果 Lua 脚本比较耗时,甚至 Lua 脚本存在问题,那么此时 Lua 脚本的执行会阻塞 Redis ,直到脚本执行完毕或者外部干预将其结束
有一点需要注意,如果Lua脚本正在执行写操作,script kill
命令不会生效,这时只能等待脚本执行结束,或使用shutdown save
停掉 Redis 服务
使用 lua 的优点
- Lua脚本在 Redis 中是原子执行的,执行过程中不会插入其他命令
- Lua脚本可以帮助开发和运维人员创造出自己定制的命令,并可以将这些命令存放在内存中,实现复用的效果
- Lua脚本可以将多条命令一次性打包,有效减少网络开销
在 lua 脚本中调用 Redis 方法
可参看redis官方文档
有两种方式可以调用
- redis.call()
- redis.pcall()
这两种方法都可以调用,区别是 call()
方法是遇到异常就停止执行并直接返回错误,而 pcall()
遇到异常会忽略掉继续执行
1 |
|
使用 scan 进行批量删除的例子
一个使用 Lua 脚本执行 Redis scan 命令进行批量删除的例子,文件名为del-batch.lua
1 |
|
调用
1 |
|
执行了之后会删除符合规则 TEST_KEY*
的 key
调用结果
1 |
|