前言
为了在我的一个基本库中降低与Redis的通讯成本,我将一系列操作封装到LUA脚本中,借助Redis提供的EVAL命令来简化操作。
EVAL能够提供的特性:
- 可以在LUA脚本中封装若干操作,如果有多条Redis指令,封装好之后只需向Redis一次性发送所有参数即可获得结果
- Redis可以保证Lua脚本运行期间不会有其他命令插入执行,提供像数据库事务一样的原子性
- Redis会根据脚本的SHA值缓存脚本,已经缓存过的脚本不需要再次传输Lua代码,减少了通信成本,此外在自己代码中改变Lua脚本,执行时Redis必定也会使用最新的代码。
导入常见的Go库如 "github.com/go-redis/redis",就可以实现以下代码。
生成一段Lua脚本
该变量创建时,Lua代码不会被执行,也不需要有已存的Redis连接。
Redis提供的Lua脚本支持,默认有KEYS、ARGV两个数组,KEYS代表脚本运行时传入的若干键值,ARGV代表传入的若干参数。由于Lua代码需要保持简洁,难免难以读懂,最好为这些参数写一些注释
注意:上面一段代码使用``跨行,`所在的行虽然空白回车,也会被认为是一行,报错时不要看错代码行号。
运行一段Lua脚本
运行时,Run将会先通过EVALSHA尝试通过缓存运行脚本。如果没有缓存,则使用EVAL运行,这时Lua脚本才会被整个传入Redis。
Lua脚本的限制
- Redis不提供引入额外的包,例如os等,只有redis这一个包可用。
- Lua脚本将会在一个函数中运行,所有变量必须使用local声明
- return返回多个值时,Redis将会只给你第一个
脚本中的类型限制
err = redis.Nilreturn redis.error_reply("My Error")
如果脚本运行了很久会发生什么?
Lua脚本运行期间,为了避免被其他操作污染数据,这期间将不能执行其它命令,一直等到执行完毕才可以继续执行其它请求。当Lua脚本执行时间超过了lua-time-limit时,其他请求将会收到Busy错误,除非这些请求是SCRIPT KILL(杀掉脚本)或者SHUTDOWN NOSAVE(不保存结果直接关闭Redis)
更多内容参考以下地址,我这里主要是根据使用Go的经验提供一些总结。https://redis.io/commands/eval
一段更“复杂”的脚本,它要求在获取一个key值时,如果该值访问较多,就延长生存周期。此外还要比较更新时间,如果不需要更新,则直接返回取到的值,否则返回redis.Nil
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对球儿工具的支持。