此页面正在审核中。 本页面可能不正确、包含无效链接和/或需要技术审查。未来它可能会有较大改动或被完全删除。
Valkey 内置了一个 Lua 5.1 解释器。该解释器运行用户定义的临时脚本和函数。脚本在沙盒环境中运行,并且只能访问特定的 Lua 包。本页面描述了执行环境中可用的包和 API。
沙盒环境
沙盒化的 Lua 环境旨在防止意外误用并减少服务器环境中的潜在威胁。
脚本绝不应尝试访问 Valkey 服务器的底层主机系统。这包括文件系统、网络以及任何尝试执行 API 不支持的系统调用的行为。
脚本应仅操作存储在 Valkey 中的数据以及作为执行参数提供的数据。
全局变量和函数
沙盒化的 Lua 执行环境会阻止全局变量和函数的声明。阻止全局变量是为了确保脚本和函数不会尝试维护除存储在 Valkey 中的数据之外的任何运行时上下文。在(有些不常见)需要在多次执行之间维护上下文的用例中,您应该将上下文存储在 Valkey 的键空间中。
尝试执行以下代码片段时,Valkey 将返回错误
my_global_variable = 'some value'
以下全局函数声明也类似
function my_global_function()
-- Do something amazing
end
当您的脚本尝试访问运行时环境中未定义的任何全局变量时,您也会收到类似的错误
-- The following will surely raise an error
return an_undefined_global_variable
相反,所有变量和函数定义都必须声明为局部变量。为此,您需要在声明前加上 local
关键字。例如,以下代码片段将被 Valkey 视为完全有效
local my_local_variable = 'some value'
local function my_local_function()
-- Do something else, but equally amazing
end
注意:沙盒尝试阻止使用全局变量。利用 Lua 的调试功能或其他方法(例如修改用于实现全局变量保护的元表)来规避沙盒并不困难。然而,意外规避保护是困难的。如果用户干扰了 Lua 的全局状态,AOF 和复制的一致性将无法保证。换句话说,就是不要这样做。
导入的 Lua 模块
沙盒执行环境中不支持使用导入的 Lua 模块。沙盒执行环境通过禁用 Lua 的 require
函数来阻止模块加载。
Valkey 自带且您可以在脚本中使用的库仅列在运行时库部分下。
运行时全局变量
虽然沙盒阻止用户声明全局变量,但执行环境已预先填充了其中一些。
其中一些指定了“起始版本”。未指定“起始版本”的在所有维护版本中均可用。
KEYS
全局变量
- 在脚本中可用:是
- 在函数中可用:否
重要提示:为确保脚本在独立部署和集群部署中都能正确执行,函数访问的所有键名都必须明确作为输入键参数提供。脚本应只访问作为输入参数提供的键。脚本绝不应访问程序化生成名称的键,或基于数据库中存储的数据结构内容生成名称的键。
KEYS
全局变量仅适用于临时脚本。它预先填充了所有键名输入参数。
ARGV
全局变量
- 在脚本中可用:是
- 在函数中可用:否
ARGV
全局变量仅在临时脚本中可用。它预先填充了所有常规输入参数。
server
单例
- 起始版本:7.2.5
- 在脚本中可用:是
- 在函数中可用:是
server
单例是可从所有脚本访问的对象实例。它提供了从脚本与 Valkey 交互的 API。以下是 server
对象实例提供的 API。
注意:为了与 Redis 兼容,Valkey 还暴露了一个顶层 redis
对象,它暴露了与 server
对象完全相同的 API 集。Valkey 无意放弃对这个 redis
API 的兼容性,但建议新开发的脚本使用 server
对象。
server
对象字段(函数和变量)
server.call(command [,arg...])
- 在脚本中可用:是
- 在函数中可用:是
server.call()
函数调用给定的 Valkey 命令并返回其回复。其输入是命令和参数,一旦调用,它就会在 Valkey 中执行命令并返回回复。
例如,我们可以从脚本中调用 ECHO
命令并返回其回复,如下所示
return server.call('ECHO', 'Echo, echo... eco... o...')
如果 server.call()
触发运行时异常,原始异常将自动作为错误返回给用户。因此,尝试执行以下临时脚本将失败并生成运行时异常,因为 ECHO
仅接受一个参数
127.0.0.1:6379> EVAL "return server.call('ECHO', 'Echo,', 'echo... ', 'eco... ', 'o...')" 0
(error) ERR Wrong number of args calling Valkey command from script script: b0345693f4b77517a711221050e76d24ae60b7f7, on @user_script:1.
请注意,调用可能因各种原因失败,请参阅低内存条件下的执行和脚本标志
要处理 Valkey 运行时错误,请改用 server.pcall()
。
server.pcall(command [,arg...])
- 在脚本中可用:是
- 在函数中可用:是
此函数可处理 Valkey 服务器引发的运行时错误。server.pcall()
函数的行为与 server.call()
完全相同,不同之处在于它
- 始终返回一个回复。
- 从不抛出运行时异常,如果服务器抛出运行时异常,则返回一个
server.error_reply
代替。
以下示例演示了如何在临时脚本的上下文中,使用 server.pcall()
拦截和处理运行时异常。
local reply = server.pcall('ECHO', unpack(ARGV))
if reply['err'] ~= nil then
-- Handle the error sometime, but for now just log it
server.log(server.LOG_WARNING, reply['err'])
reply['err'] = 'ERR Something is wrong, but no worries, everything is under control'
end
return reply
使用多个参数评估此脚本将返回
127.0.0.1:6379> EVAL "..." 0 hello world
(error) ERR Something is wrong, but no worries, everything is under control
server.error_reply(x)
- 在脚本中可用:是
- 在函数中可用:是
这是一个返回错误回复的辅助函数。该辅助函数接受一个字符串参数,并返回一个 Lua 表,其中 err
字段设置为该字符串。
以下代码的结果是 error1
和 error2
在所有意图和目的上都是相同的
local text = 'ERR My very special error'
local reply1 = { err = text }
local reply2 = server.error_reply(text)
因此,两种形式都可作为从脚本返回错误回复的有效方式
127.0.0.1:6379> EVAL "return { err = 'ERR My very special table error' }" 0
(error) ERR My very special table error
127.0.0.1:6379> EVAL "return server.error_reply('ERR My very special reply error')" 0
(error) ERR My very special reply error
有关返回 Valkey 状态回复,请参阅 server.status_reply()
。有关返回其他响应类型,请参阅数据类型转换。
注意:按照惯例,Valkey 将错误字符串的第一个词用作特定错误的唯一错误代码,或使用 ERR
作为通用错误代码。建议脚本遵循此惯例,如上例所示,但这并非强制性要求。
server.status_reply(x)
- 在脚本中可用:是
- 在函数中可用:是
这是一个返回简单字符串回复的辅助函数。“OK”是 Valkey 标准状态回复的一个示例。Lua API 将状态回复表示为带有单个字段 ok
的表,该字段设置为一个简单的状态字符串。
以下代码的结果是 status1
和 status2
在所有意图和目的上都是相同的
local text = 'Frosty'
local status1 = { ok = text }
local status2 = server.status_reply(text)
因此,两种形式都可作为从脚本返回状态回复的有效方式
127.0.0.1:6379> EVAL "return { ok = 'TICK' }" 0
TICK
127.0.0.1:6379> EVAL "return server.status_reply('TOCK')" 0
TOCK
有关返回 Valkey 错误回复,请参阅 server.error_reply()
。有关返回其他响应类型,请参阅数据类型转换。
server.sha1hex(x)
- 在脚本中可用:是
- 在函数中可用:是
此函数返回其单个字符串参数的 SHA1 十六进制摘要。
例如,您可以获取空字符串的 SHA1 摘要
127.0.0.1:6379> EVAL "return server.sha1hex('')" 0
"da39a3ee5e6b4b0d3255bfef95601890afd80709"
server.log(level, message)
- 在脚本中可用:是
- 在函数中可用:是
此函数写入 Valkey 服务器日志。
它需要两个输入参数:日志级别和消息。消息是要写入日志文件的字符串。日志级别可以是以下之一
server.LOG_DEBUG
server.LOG_VERBOSE
server.LOG_NOTICE
server.LOG_WARNING
这些级别映射到服务器的日志级别。日志仅记录级别等于或高于服务器 loglevel
配置指令的消息。
以下代码片段
server.log(server.LOG_WARNING, 'Something is terribly wrong')
将在您的服务器日志中生成类似于以下内容的一行
[32343] 22 Mar 15:21:39 # Something is terribly wrong
server.setresp(x)
- 在脚本中可用:是
- 在函数中可用:是
此函数允许执行脚本在 RESP 协议版本之间切换,以处理由 server.call()
和 server.pcall()
返回的回复。它需要一个数字参数作为协议版本。默认协议版本为 2,但可以切换到版本 3。
以下是切换到 RESP3 回复的示例
server.setresp(3)
有关类型转换的更多信息,请参阅数据类型转换。
server.set_repl(x)
- 在脚本中可用:是
- 在函数中可用:否
注意:在 Redis OSS 7.0 之前,脚本默认按字面复制。从 Redis OSS 7.0(和 Valkey)开始,脚本效果复制是唯一可用的复制模式。
server.set_repl()
函数指示服务器如何处理后续写入命令的复制。它接受一个输入参数,该参数只能是以下之一
server.REPL_ALL
:将效果复制到 AOF 和副本。server.REPL_AOF
:仅将效果复制到 AOF。server.REPL_REPLICA
:仅将效果复制到副本。server.REPL_SLAVE
:与REPL_REPLICA
相同,为向后兼容而保留。server.REPL_NONE
:完全禁用效果复制。
默认情况下,当脚本开始执行时,脚本引擎会初始化为 server.REPL_ALL
设置。您可以在脚本执行期间的任何时候调用 server.set_repl()
函数以在不同的复制模式之间切换。
以下是一个简单示例
server.replicate_commands() -- Enable effects replication in versions lower than Redis OSS v7.0
server.call('SET', KEYS[1], ARGV[1])
server.set_repl(server.REPL_NONE)
server.call('SET', KEYS[2], ARGV[2])
server.set_repl(server.REPL_ALL)
server.call('SET', KEYS[3], ARGV[3])
如果您通过调用 EVAL "..." 3 A B C 1 2 3
来运行此脚本,结果将是只有键 A 和 C 在副本和 AOF 上创建。
server.replicate_commands()
- 直到版本:7.0.0
- 在脚本中可用:是
- 在函数中可用:否
此函数将脚本的复制模式从逐字复制切换到效果复制。您可以使用它来覆盖 Redis OSS 7.0 版本之前使用的默认逐字脚本复制模式。
注意:逐字脚本复制不再受支持。唯一受支持的脚本复制模式是脚本效果复制。有关更多信息,请参阅复制命令而不是脚本
server.breakpoint()
- 在脚本中可用:是
- 在函数中可用:否
使用 Valkey Lua 调试器时,此函数会触发断点。
server.debug(x)
- 在脚本中可用:是
- 在函数中可用:否
此函数在 Valkey Lua 调试器控制台中打印其参数。
server.acl_check_cmd(command [,arg...])
- 起始版本:7.0.0
- 在脚本中可用:是
- 在函数中可用:是
此函数用于检查当前运行脚本的用户是否具有 ACL 权限以执行给定命令和给定参数。
如果当前用户有权限执行该命令(通过调用 server.call 或 server.pcall),则返回布尔值 true
,否则返回 false
。
如果传入的命令或其参数无效,该函数将引发错误。
server.register_function
- 起始版本:7.0.0
- 在脚本中可用:否
- 在函数中可用:是
此函数仅在 FUNCTION LOAD
命令的上下文中可用。调用时,它会将一个函数注册到已加载的库中。该函数可以 positional 参数或 named 参数调用。
位置参数:server.register_function(name, callback)
server.register_function
的第一个参数是一个 Lua 字符串,表示函数名。server.register_function
的第二个参数是一个 Lua 函数。
使用示例
127.0.0.1:6379> FUNCTION LOAD "#!lua name=mylib\n server.register_function('noop', function() end)"
命名参数:server.register_function{function_name=name, callback=callback, flags={flag1, flag2, ..}, description=description}
命名参数变体接受以下参数
- function_name:函数名称。
- callback:函数回调。
- flags:字符串数组,每个都是函数标志(可选)。
- description:函数描述(可选)。
function_name 和 callback 都是强制性的。
使用示例
127.0.0.1:6379> FUNCTION LOAD "#!lua name=mylib\n server.register_function{function_name='noop', callback=function() end, flags={ 'no-writes' }, description='Does nothing'}"
脚本标志
重要提示:请谨慎使用脚本标志,误用可能会产生负面影响。请注意,Eval 脚本的默认设置与下面提到的函数的默认设置不同,请参阅Eval 标志
当您注册一个函数或加载一个 Eval 脚本时,服务器不知道它是如何访问数据库的。默认情况下,Valkey 假定所有脚本都读取和写入数据。这会产生以下行为
- 它们可以读写数据。
- 它们可以在集群模式下运行,但无法运行访问不同哈希槽键的命令。
- 为避免不一致读取,禁止对过期副本执行操作。
- 为避免超出配置阈值,禁止在低内存下执行。
您可以使用以下标志并指示服务器以不同方式处理脚本的执行
-
no-writes
:此标志表示脚本只读取数据,从不写入。默认情况下,Valkey 会拒绝在只读副本上执行带标志的脚本(带有 shebang 的函数和 Eval 脚本),因为它们可能会尝试执行写入操作。同样,服务器也不允许使用
FCALL_RO
/EVAL_RO
调用脚本。最后,当数据持久性因磁盘错误而面临风险时,执行也会被阻止。使用此标志允许执行脚本
- 使用
FCALL_RO
/EVAL_RO
- 在只读副本上。
- 即使出现磁盘错误(Valkey 无法持久化,因此拒绝写入)。
- 当超过内存限制时,因为它意味着脚本不会增加内存消耗(请参阅下面的
allow-oom
)
但是请注意,如果脚本尝试调用写入命令,服务器将返回错误。另请注意,目前
PUBLISH
、SPUBLISH
和PFCOUNT
在脚本中也被视为写入命令,因为它们可能会尝试将命令传播到副本和 AOF 文件。有关更多信息,请参阅只读脚本
- 使用
-
allow-oom
:使用此标志允许脚本在服务器内存不足 (OOM) 时执行。除非使用此标志,否则 Valkey 将拒绝在 OOM 状态下执行带标志的脚本(带有 shebang 的函数和 Eval 脚本)。此外,当您使用此标志时,脚本可以调用任何 Valkey 命令,包括通常在此状态下不允许的命令。指定
no-writes
或使用FCALL_RO
/EVAL_RO
也意味着脚本可以在 OOM 状态下运行(无需指定allow-oom
) -
allow-stale
:当replica-serve-stale-data
配置设置为no
时,此标志允许在过期副本上运行带标志的脚本(带有 shebang 的函数和 Eval 脚本)。Valkey 可以设置为通过让过期副本返回运行时错误来防止因使用旧数据而导致的数据一致性问题。对于不访问数据的脚本,可以设置此标志以允许过期的 Valkey 副本运行该脚本。但请注意,脚本仍将无法执行任何访问过期数据的命令。
-
no-cluster
:此标志会导致脚本在 Valkey 集群模式下返回错误。Valkey 允许脚本在独立模式和集群模式下执行。设置此标志可防止在集群节点上执行脚本。
-
allow-cross-slot-keys
:允许脚本访问来自多个槽的键的标志。Valkey 通常会阻止任何单个命令访问哈希到多个槽的键。此标志允许脚本打破此规则,并访问脚本中访问多个槽的键。向脚本声明的键仍然始终需要哈希到单个槽。不鼓励访问多个槽的键,因为应用程序应设计为一次只访问单个槽的键,从而允许槽在 Valkey 服务器之间移动。
当集群模式被禁用时,此标志无效。
server.SERVER_VERSION
- 起始版本:7.2.5
- 在脚本中可用:是
- 在函数中可用:是
将当前 Valkey 服务器版本作为 Lua 字符串返回。回复格式为 MM.mm.PP
,其中
- MM:主版本。
- mm:次版本。
- PP:补丁级别。
server.REDIS_VERSION
- 起始版本:7.0.0
- 在脚本中可用:是
- 在函数中可用:是
将当前 Redis 兼容版本作为 Lua 字符串返回。回复格式为 MM.mm.PP
,其中
- MM:主版本。
- mm:次版本。
- PP:补丁级别。
server.SERVER_VERSION_NUM
- 起始版本:7.2.5
- 在脚本中可用:是
- 在函数中可用:是
将当前 Valkey 服务器版本作为数字返回。回复是一个十六进制值,结构为 0x00MMmmPP
,其中
- MM:主版本。
- mm:次版本。
- PP:补丁级别。
server.REDIS_VERSION_NUM
- 起始版本:7.0.0
- 在脚本中可用:是
- 在函数中可用:是
将当前 Redis 兼容版本作为数字返回。回复是一个十六进制值,结构为 0x00MMmmPP
,其中
- MM:主版本。
- mm:次版本。
- PP:补丁级别。
数据类型转换
除非引发运行时异常,否则 server.call()
和 server.pcall()
会将执行命令的回复返回给 Lua 脚本。Valkey 从这些函数返回的回复会自动转换为 Lua 的原生数据类型。
同样,当 Lua 脚本使用 return
关键字返回回复时,该回复会自动转换为 RESP 协议。
换句话说:Valkey 的回复与 Lua 的数据类型之间存在一对一映射,Lua 的数据类型与 RESP 协议数据类型之间也存在一对一映射。底层设计使得如果将 RESP 类型转换为 Lua 类型,然后再转换回 RESP 类型,结果与初始值相同。
从 Valkey 回复(即 server.call()
和 server.pcall()
的回复)到 Lua 数据类型的类型转换取决于脚本使用的 RESP 协议版本。脚本执行期间的默认协议版本是 RESP2。脚本可以通过调用 server.setresp()
函数来切换回复的协议版本。
从脚本返回的 Lua 数据类型的类型转换取决于用户选择的协议(参见 HELLO
命令)。
以下各节根据协议版本描述 Lua 和 Valkey 之间的类型转换规则。
RESP2 到 Lua 类型转换
以下类型转换规则默认适用于执行环境,以及调用 server.setresp(2)
之后
- RESP2 整型回复 -> Lua 数字
- RESP2 批量字符串回复 -> Lua 字符串
- RESP2 数组回复 -> Lua 表(可能嵌套其他 Valkey 数据类型)
- RESP2 状态回复 -> 带有单个 ok 字段的 Lua 表,包含状态字符串
- RESP2 错误回复 -> 带有单个 err 字段的 Lua 表,包含错误字符串
- RESP2 空批量回复和空多批量回复 -> Lua 布尔假类型
Lua 到 RESP2 类型转换
以下类型转换规则默认适用,以及在用户调用 HELLO 2
之后适用
- Lua 数字 -> RESP2 整型回复(数字转换为整数)
- Lua 字符串 -> RESP 批量字符串回复
- Lua 表(索引的、非关联数组)-> RESP2 数组回复(如果在表中遇到第一个 Lua
nil
值,则截断) - 带有单个 ok 字段的 Lua 表 -> RESP2 状态回复
- 带有单个 err 字段的 Lua 表 -> RESP2 错误回复
- Lua 布尔假 -> RESP2 空批量回复
还有一条额外的 Lua 到 Valkey 转换规则,它没有对应的 Valkey 到 Lua 转换规则
- Lua 布尔
true
-> RESP2 整型回复,值为 1。
关于将 Lua 转换为 Valkey 数据类型,还有三条需要注意的规则
- Lua 只有一种数值类型,即 Lua 数字。整数和浮点数之间没有区别。因此,我们总是将 Lua 数字转换为整数回复,如果存在小数部分,则将其移除。如果您想返回 Lua 浮点数,它应该作为字符串返回,就像 Valkey 本身一样(例如,请参阅
ZSCORE
命令)。 - 由于 Lua 的表语义,在 Lua 数组中不能简单地包含
nil
。因此,当 Valkey 将 Lua 数组转换为 RESP 时,一旦遇到 Luanil
值,转换就会停止。 - 当一个 Lua 表是包含键及其相应值的关联数组时,转换后的 Valkey 回复将不包含它们。
Lua 到 RESP2 类型转换示例
127.0.0.1:6379> EVAL "return 10" 0
(integer) 10
127.0.0.1:6379> EVAL "return { 1, 2, { 3, 'Hello World!' } }" 0
1) (integer) 1
2) (integer) 2
3) 1) (integer) 3
1) "Hello World!"
127.0.0.1:6379> EVAL "return server.call('get','foo')" 0
"bar"
最后一个示例演示了在 Lua 中接收并返回 server.call()
(或 server.pcall()
)的精确返回值,就像直接调用该命令时返回的那样。
以下示例展示了浮点数以及包含 `nil` 和键的数组是如何处理的
127.0.0.1:6379> EVAL "return { 1, 2, 3.3333, somekey = 'somevalue', 'foo', nil , 'bar' }" 0
1) (integer) 1
2) (integer) 2
3) (integer) 3
4) "foo"
如您所见,浮点值 3.333 被转换为整数 3,somekey 键及其值被省略,并且字符串“bar”未返回,因为它前面有一个 nil
值。
RESP3 到 Lua 类型转换
RESP3 是 Valkey 使用的协议的较新版本。它可作为可选功能使用。
执行中的脚本可以在其执行期间调用 server.setresp
函数,并切换用于从 Valkey 命令返回回复的协议版本(可通过 server.call()
或 server.pcall()
调用)。
一旦 Valkey 的回复采用 RESP3 协议,所有RESP2 到 Lua 的转换规则均适用,并增加以下内容
- Map 回复 -> 带有单个 map 字段的 Lua 表,其中包含一个表示映射字段和值的 Lua 表。
- Set 回复 -> 带有单个 set 字段的 Lua 表,其中包含一个表示集合元素的 Lua 表作为字段,每个字段的值均为 Lua 布尔值
true
。 - Null -> Lua
nil
。 - True 回复 -> Lua 布尔值
true
。 - False 回复 -> Lua 布尔值
false
。 - Double 回复 -> 带有单个
double
字段的 Lua 表,其中包含一个表示双精度值的 Lua 数字。 - 大数回复 -> 带有单个
big_number
字段的 Lua 表,其中包含一个表示大数值的 Lua 字符串(自 Redis OSS 7.0 起)。 - 逐字字符串回复 -> 带有单个
verbatim_string
字段的 Lua 表,其中包含一个带有string
和format
两个字段的 Lua 表,分别表示逐字字符串及其格式(自 Redis OSS 7.0 起)。
Lua 到 RESP3 类型转换
无论脚本在调用 server.call()
或 server.pcall()
时选择哪种协议版本(通过 server.setresp()
函数设置)来返回回复,用户都可以选择使用 RESP3(通过 HELLO 3
命令)进行连接。尽管传入客户端连接的默认协议是 RESP2,但脚本应遵循用户的偏好并返回适当类型的 RESP3 回复,因此在这种情况下,以下规则适用于Lua 到 RESP2 类型转换部分中指定的规则之上。
- Lua 布尔值 -> RESP3 布尔回复(请注意,这与 RESP2 相比是一个变化,在 RESP2 中,返回布尔值 Lua
true
会向 Valkey 客户端返回数字 1,而返回false
则会返回null
。 - 带有单个
map
字段的 Lua 表(设置为关联 Lua 表)-> RESP3 map 回复。 - 带有单个
set
字段的 Lua 表(设置为关联 Lua 表)-> RESP3 set 回复。值可以设置为任何内容,并且无论如何都会被丢弃。 - 带有单个
double
字段的 Lua 表(设置为关联 Lua 表)-> RESP3 double 回复。 - Lua
nil
-> RESP3 null。
然而,如果连接设置为使用 RESP2 协议,即使脚本回复了 RESP3 类型响应,Valkey 也会自动将回复执行 RESP3 到 RESP2 的转换,就像常规命令一样。这意味着,例如,将 RESP3 映射类型返回给 RESP2 连接将导致回复被转换为一个扁平的 RESP2 数组,该数组由交替的字段名和它们的值组成,而不是 RESP3 映射。
关于脚本的其他注意事项
在脚本中使用 SELECT
您可以从 Lua 脚本中调用 SELECT
命令,就像您使用任何普通客户端连接一样。Lua 脚本选择的数据库仅影响脚本的执行上下文,而不会修改调用脚本的客户端所选的数据库。
运行时库
Valkey Lua 运行时环境总是预先导入了一些库。
以下标准 Lua 库可供使用
此外,以下外部库已加载并可供脚本访问
os 库
- 起始版本:8.0.0
- 在脚本中可用:是
- 在函数中可用:是
os 提供了处理日期、时间以及系统命令的一组函数。更多详情可在操作系统设施中找到。请注意,出于沙盒安全考虑,目前仅暴露以下 os 函数
os.clock()
struct 库
- 在脚本中可用:是
- 在函数中可用:是
struct 是一个用于在 Lua 中打包和解包类 C 结构体的库。它提供以下函数
所有 struct 函数都期望它们的第一个参数是一个格式字符串。
struct 格式
以下是 struct 函数的有效格式字符串
>
: 大端序<
: 小端序![num]
: 对齐x
: 填充b/B
: 有符号/无符号字节h/H
: 有符号/无符号短整型l/L
: 有符号/无符号长整型T
: size_ti/In
: 大小为 n 的有符号/无符号整数(默认为 int 的大小)cn
: n 个字符序列(来自/到字符串);打包时,n == 0 表示整个字符串;解包时,n == 0 表示使用之前读取的数字作为字符串的长度。s
: 零终止字符串f
: 浮点数d
: 双精度浮点数
struct.pack(x)
此函数从值返回一个结构体编码的字符串。它接受一个struct 格式字符串作为其第一个参数,然后是要编码的值。
使用示例
127.0.0.1:6379> EVAL "return struct.pack('HH', 1, 2)" 0
"\x01\x00\x02\x00"
struct.unpack(x)
此函数从结构体中返回解码后的值。它接受一个struct 格式字符串作为其第一个参数,然后是编码后的结构体字符串。
使用示例
127.0.0.1:6379> EVAL "return { struct.unpack('HH', ARGV[1]) ]: " 0 "\x01\x00\x02\x00"
1) (integer) 1
2) (integer) 2
3) (integer) 5
struct.size(x)
此函数返回结构体的大小(以字节为单位)。它接受一个struct 格式字符串作为其唯一参数。
使用示例
127.0.0.1:6379> EVAL "return struct.size('HH')" 0
(integer) 4
cjson 库
- 在脚本中可用:是
- 在函数中可用:是
cjson 库提供了 Lua 中快速的 JSON 编码和解码功能。它提供以下函数。
cjson.encode(x)
此函数返回为其参数提供的 Lua 数据类型的 JSON 编码字符串。
使用示例
127.0.0.1:6379> EVAL "return cjson.encode({ ['foo'] = 'bar' ]: )" 0
"{\"foo\":\"bar\"}"
cjson.decode(x)
此函数从为其参数提供的 JSON 编码字符串返回 Lua 数据类型。
使用示例
127.0.0.1:6379> EVAL "return cjson.decode(ARGV[1])['foo']" 0 '{"foo":"bar"]: '
"bar"
cmsgpack 库
- 在脚本中可用:是
- 在函数中可用:是
cmsgpack 库提供了 Lua 中快速的 MessagePack 编码和解码功能。它提供以下函数。
cmsgpack.pack(x)
此函数返回给定 Lua 数据类型的打包字符串编码。
使用示例
127.0.0.1:6379> EVAL "return cmsgpack.pack({'foo', 'bar', 'baz'})" 0
"\x93\xa3foo\xa3bar\xa3baz"
cmsgpack.unpack(x)
此函数从解码其输入字符串参数中返回解包后的值。
使用示例
127.0.0.1:6379> EVAL "return cmsgpack.unpack(ARGV[1])" 0 "\x93\xa3foo\xa3bar\xa3baz"
1) "foo"
2) "bar"
3) "baz"
bit 库
- 在脚本中可用:是
- 在函数中可用:是
bit 库提供了数字上的按位操作。其文档位于 Lua BitOp 文档中。它提供以下函数。
bit.tobit(x)
将数字标准化为位操作的数值范围并返回。
使用示例
127.0.0.1:6379> EVAL 'return bit.tobit(1)' 0
(integer) 1
bit.tohex(x [,n])
将其第一个参数转换为十六进制字符串。十六进制数字的数量由可选的第二个参数的绝对值给出。
使用示例
127.0.0.1:6379> EVAL 'return bit.tohex(422342)' 0
"000671c6"
bit.bnot(x)
返回其参数的按位非。
bit.bnot(x)
bit.bor(x1 [,x2...])
, bit.band(x1 [,x2...])
和 bit.bxor(x1 [,x2...])
返回其所有参数的按位或、按位与或按位异或。请注意,允许超过两个参数。
使用示例
127.0.0.1:6379> EVAL 'return bit.bor(1,2,4,8,16,32,64,128)' 0
(integer) 255
bit.lshift(x, n)
, bit.rshift(x, n)
和 bit.arshift(x, n)
返回其第一个参数的按位逻辑左移、按位逻辑右移或按位算术右移,移动的位数由第二个参数给出。
bit.rol(x, n)
和 bit.ror(x, n)
返回其第一个参数的按位左旋或按位右旋,旋转的位数由第二个参数给出。从一侧移出的位会从另一侧移回。
bit.bswap(x)
交换其参数的字节并返回。这可用于将小端序 32 位数字转换为大端序 32 位数字,反之亦然。