RedisLua脚本
Lua脚本
使用脚本可以直接在服 务器端执行 Redis 命令,一般的数据 处理操作可以直接使用 Lua 语言或者 Lua 解释器提供的函数 库来完成,不必再返回 给客户端进行处理。
所有脚本都是以事 务的形式来执行的,脚本在 执行过程中不会被其他工作打断,也不会引起任何 竞争条件,完全可以使用 Lua 脚本来代替事 务和乐观锁。
所有脚本都是可重用的,也即是 说,重复执行相同的操作 时,只要调用储存在服务器内部的脚本 缓存就可以了,不用重新 发送整个脚本,从而尽可能地 节约网络资源。
执行 Lua 脚本
1 | EVAL script numkeys key [key ...] arg [arg ...] |
- script 参数是要执行的 Lua 脚本。
- numkeys 是脚本要处理的数据库键的数量,之后的 key [key …] 参数指定了脚本要 处理的数据库键,被传入的键可以在脚本里面通 过访问 KEYS 数组来取得,比如 KEYS[1] 就取出第一个 输入的键,KEYS[2] 取出第二个输入的键,诸如此类。
- arg [arg …] 参数指定了脚本要用到的参数,在脚本里面可以通 过访问 ARGV 数组来获取这些参数。显式地指定脚本里面用到的 键是为了配合 Redis 集群对键的检查,如果不这样做的话,在集群里面使用脚本可能会出 错。
另外,通过显式地指定脚本要用到的数据 库键以及相关参数,而不是将数据 库键和参数硬写在脚本里面,用户可以更方便地重用同一个脚本。
1 | redis> EVAL "return redis.call('PING')" 0 # 在 Lua 脚本里面执行 PING 命令 |
redis.call() 和 redis.pcall() 的区别
redis.call() 和 redis.pcall() 都可以用来执行 Redis 命令,它们的不同之处在于,当被执行的脚本出错时:
- redis.call() 会返回出错脚本的名字以及 EVAL 命令的错误信息
- redis.pcall() 只返回 EVAL 命令的错误信息。
1 | redis> EVAL "return redis.call('NotExistsCommand')" 0 |
换句话来说,在被执行的脚本出错时, redis.call() 可以提供更详细的错误信息,方便进行查错。
使用 EVALSHA 来减少网络资源损耗
任何 Lua 脚本,只要被 EVAL 命令执行过一次,就会被 储存到服务器的脚本缓存里面,用户只要通过 EVALSHA 命令,指定被 缓存脚本的 SHA1 值,就可以在不 发送脚本的情况下,再次 执行脚本:
1 | EVALSHA sha1 numkeys key [key ...] arg [arg ...] |
通过 SHA1 值来重用返回 ‘hello world’ 信息的脚本:
1 | redis> EVAL "return 'hello world'" 0 |
通过 SHA1 值来重用之前实现的 ZDECRBY 命令,这样就不用每次都 发送整个脚本了:
1 | redis> EVALSHA 918130cae39ff0759b8256948742f77300a91cb2 1 salary 500 peter |
脚本管理命令
检查 sha1 值所代表的脚本是否已经被加入到脚本缓存里面,是的话返回 1 ,不是的话返回 0 。
1 | SCRIPT EXISTS sha1 [sha1 ...] |
将脚本储存到脚本缓存里面,等待将来 EVALSHA 使用。
1 | SCRIPT LOAD script |
清除脚本缓存储存的所有脚本。
1 | SCRIPT FLUSH |
杀死运行超时的脚本。如果脚本已经执行过写入操作,那么还需要使用 SHUTDOWN NOSAVE 命令来强制服务器不保存数据,以免错误的数据被保存到数据库里面。
1 | SCRIPT KILL |