随笔 - 171  文章 - 0  评论 - 0  阅读 - 62466

lua脚本

Redis通过内置的lua编译/解释器,可以使用EVAL命令对lua脚本进行求值。

脚本的命令是原子的,RedisServer在执行脚本命令中,不允许插入新的命令;同时脚本的命令可以复制,RedisServer在获得脚本后不执行,生成标识返回,Client根据标识就可以随时执行。

EVAL命令

通过执行rediseval命令,可以运行一段lua脚本。

  • script参数:是一段Lua脚本程序,它会被运行在Redis服务器上下文中,这段脚本不必(也不应该)定义为一个Lua函数。
  • numkeys参数:用于指定键名参数的个数。
  • key [key ...]参数: EVAL的第三个参数开始算起,使用了numkeys个键(key),表示在脚本中所用到的那些Redis(key),这些键名参数可以在Lua中通过全局变量KEYS数组,用1为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)

如果使用的是Redis集群,并且有多个key,需要保证每个key落在同一个slot上,否则会报错"-ERR eval/evalsha command keys must be in same slot\r\n",可以使用hashtag来保证。

  • arg [arg ...]参数:可以在Lua中通过全局变量ARGV数组访问,访问的形式和KEYS变量类似(ARGV[1] 、 ARGV[2] ,诸如此类)
eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second

lua脚本中调用Redis命令

redis.call()返回值就是redis命令执行的返回值;如果出错,则返回错误信息,不继续执行。

redis.pcall()返回值就是redis命令执行的返回值;如果出错,则记录错误信息,继续执行。

注意事项:在脚本中,使用return语句将返回值返回给客户端,如果没有return,则返回nil。

EVALSHA

EVAL 命令要求你在每次执行脚本的时候都发送一次脚本主体(script body)Redis 有一个内部的缓存机制,因此它不会每次都重新编译脚本,不过在很多场合,付出无谓的带宽来传送脚本主体并不是最佳选择。

为了减少带宽的消耗, Redis 实现了 EVALSHA 命令,它的作用和 EVAL 一样,都用于对脚本求值,但它接受的第一个参数不是脚本,而是脚本的 SHA1 校验和(sum)。如果没有对应的脚本,会抛出NOSCRIPT异常。

SCRIPT

SCRIPT FLUSH 清除所有脚本缓存。
SCRIPT EXISTS 根据给定的脚本校验和,检查指定的脚本是否存在于脚本缓存。
SCRIPT LOAD 将一个脚本装入脚本缓存,返回SHA1摘要,但并不立即运行它。
SCRIPT KILL 杀死当前正在运行的脚本。

Redis整合Lua主要是为了性能以及事务的原子性,因为redis提供的事务功能太差(为提供其自身性能甚至都不提供回滚)。

脚本执行超时时间

通过lua-time-limit配置,生产环境配置lua-time-limit=5000,单位ms。

优化

本地启动时通过scriptLoad对lua脚本进行加载,获取脚本的校验和,以脚本的md5值作为key,缓存在redis上,执行时从缓存获取脚本校验和,通过EVALSHA方式执行,减少带宽占用。

防止脚本失效的情况下,对NOSCRIPT异常进行处理,重新加载脚本。

posted on   zhengbiyu  阅读(230)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示