redis从2.6.0版本引入对lua的支持
redis服务器以原子方式执行lua脚本,在执行完整个lua脚本前服务器不会执行其他客户端的命令或脚本(即阻塞其他客户端发送的命令执行)
- 如何使用redis的lua脚本特性
- 如何管理脚本
- 如何使用lua环境内置的函数库
- 如何调试脚本
14.1 EVAL:执行脚本
|
|
其中:
- script 指的是lua脚本
- numKeys 指定了有多少个key,后面紧跟这么多个key。在lua中,可以通过
KEYS
数组进行访问,1-index - 任意个arg,lua脚本中通过
ARGV
数组进行访问,1-index
14.1.1 在lua脚本中使用redis服务器提供的命令
redis.call()
redis.pcall()
执行遇到错误时会返回一个包含错误信息的lua表格
14.1.2 值转换
- 当脚本调用
redis.call()
的时候,传入的lua值将会被转换成redis协议的值 redis.call()
返回值将会从redis值被装换为lua值- lua脚本执行结束时,将会把lua值转换为redis协议值
将redis协议值转换成lua值的规则
将lua值转换为redis协议值的规则
注意:
- 因为浮点数的lua值被转换为redis值时会被强转为整型,需要有意识的用lua的
tostring()
转换后再返回给redis
在脚本中切换数据库
14.2 SCRIPT LOAD 和 EVALSHA: 缓存、执行脚本
SCRIPT LOAD 将lua脚本加载到redis服务器中,并返回标识脚本的sha1值:
|
|
EVALSHA 根据提供的sha1值调用对应的lua脚本 :
|
|
14.3 脚本管理
SCRIPT EXISTS sha1 [sha1 ...]
检查脚本是否存在- 存在返回1,否则返回0
SCRIPT FLUSH
移除redis服务器所有缓存的脚本SCRIPT KILL
强制停止正在运行的脚本- 配置选项
lua-time-limit
定义了lua脚本可以不受限制运行的时长,默认5000 ms - 当超过
lua-time-limit
时长时,想服务器发送请求的客户端将得到一个错误回复,提示用户使用SCRIPT KILL
或SHUTDOWN NOSAVE
- 注意,如果超过
lua-time-limit
后,如果在已经执行过写操作的情况下,强行SCRIPT KILL
可能会产生脏数据,事实上若执行SCRIPT KILL
会报错提示UNKILLABLE
。此时只能等待脚本执行完毕,或者执行SHUTDOWN NOSAVE
在不执行持久化操作的情况下关闭服务器
- 配置选项
14.4 redis给lua提供的内置函数库
redis提供了以下函数库、函数包,供编写lua脚本时使用:
- base、table、string、math (lua标准库)
- redis (调用redis功能专用的定制包)
- bit、struct、cjson、cmsgpack (从外部引入的数据处理包)
14.4.1 redis包
- reids.log()
- 用redis服务器打日志
- 提供四个级别:
redis.LOG_DEBUG
,redis.LOG_VERBOSE
,redis.LOG_NOTICE
,redis.LOG_WARNING
- redis.sha1hex()
- 计算给定字符串的SHA1校验和
- redis.error_reply()
- 返回redis错误回复
- 返回一个只包含err字段的lua table, 其中,err字段的值则是给定的错误信息
- 例如:
redis.error_reply('something wrong')
将返回table{err='something wrong'}
- redis.status_reply()
- 返回redis状态回复
- 例如,
redis.status_reply('all is well')
将返回table{ok='all is well'}
- redis.breakpoint()
- redis.debug()
- redis.replicate_commands()
- redis.set_repl()
14.4.2 bit包
bit包可以对lua脚本中的数字进行二进制位操作:
- bit.tohex()
- bit.bnot()
- bit.bor()
- bit.band()
- bit.bxor()
- ….
14.4.3 struct 包
struct 包提供了能够在lua值以及c结构体之间进行转换的基本设施
struct.pack(fmt, v1, v2, ...)
struct.unpack(fmt, s, [i])
struct.size(fmt)
14.4.4 cjson包
提供json编码和解码操作 :
cjson.encode(value)
cjson.decode(json_text)
14.4.5 cmsgpack包
为lua脚本提供快速的MessagePack打包和解包操作
cmsgpack.pack(arg1, arg2, ...)
cmsgpack.unpack(msgpack)
14.5 脚本调试
从redis3.2 开始引入一个lua调试器,简称为LDB。
用户可以通过LDB实现单步调试、添加断点、返回日志、打印调用链、重载脚本等多种功能
通过使用redis-cli
指定参数的方式使用:
|
|
调试命令:
- 动态断点
- 使用redis.debug()输出调试日志
- 执行指定的代码或指令
- 使用trace显示调用链
- 可以使用restart重新载入(修改后的)脚本
- 调试模式
- redis调试器支持两种不同的调试模式
- 1)异步调试
- 以参数
ldb
启动 - 为每个调试会话分别创建新的子进程
- 使得允许多个用户同时进行调试
- 在子进程上进行,不会阻塞服务器,也不会影响服务器数据
- 以参数
- 2)同步调试:
- 以参数
ldb-sync-mode
启动 - 直接使用服务器进程进行调试,所以同一时间只能有一个调试会话
- 会影响数据
- 以参数