内置函数库

Redis在Lua环境中内置了一些函数库,用户可以通过这些函数库对 Redis服务器进行操作,或者对给定的数据进行处理,这些函数库分别 是:

·base包 ·table包 ·string包 ·math包 ·redis包 ·bit包 ·struct包 ·cjson包 ·cmsgpack包

其中base包、table包、string包以及math包均为Lua标准库,它们的 详细信息可以在Lua参考手册中找到,网址为 http://www.lua.org/manual/5.1/ ;在其余的5个包中,redis包为调 用Redis功能专用的定制包,而bit包、struct包、cjson包以及 cmsgpack包则是从外部引入的数据处理包,本节将分别对这些包进行介绍。

redis包

除了前面已经介绍过的redis.call()函数和redis.pcall()函数之 外,redis包还包含了以下函数: ·redis.log() ·redis.sha1hex() ·redis.error_reply() ·redis.status_reply() ·redis.breakpoint() ·redis.debug() ·redis.replicate_commands() ·redis.set_repl() 本节将对以上列出的前4个函数进行介绍,与脚本调试有关的 redis.breakpoint()函数和redis.debug()函数将会在14.5节中进 行介绍,而与脚本复制有关的redis.replicate_commands()函数以 及redis.set_repl()函数则会在第18章中进行介绍。

  1. redis.log()函数

redis.log()函数用于在脚本中向Redis服务器写入日志,它接受一 个日志等级和一条消息作为参数:

redis.log(loglevel, message)

其中loglevel的值可以是以下4个日志等级的其中一个,这些日志等级与Redis服务器本身的日志等级完全一致:

·redis.LOG_DEBUG ·redis.LOG_VERBOSE ·redis.LOG_NOTICE ·redis.LOG_WARNING

当给定的日志等级超过或等同于Redis服务器当前设置的日志等级时, Redis服务器就会把给定的消息写入日志中。

比如对于一个日志等级被设置为notice的Redis服务器来说,在脚本中 执行以下语句:

redis> EVAL "redis.log(redis.LOG_WARNING, 'Something wrong!')" 0
(nil)

将导致服务器向日志写入以下消息:

1124:M 22 Mar 06:21:38.376 # Something wrong!
  1. redis.shalhex()函数

redis.sha1hex()函数可以计算出给定字符串输入的SHA1校验和:

redis.sha1hex(string)

作为例子,以下代码展示了如何在脚本中计算字符串’show me your sha1’的SHA1校验和:

redis> EVAL "return redis.sha1hex('show me your sha1')" 0
"e00ecdbe6ea77b31972c28dccad6aceba9822a12"

3.redis.error_reply()函数和redis.status_reply()函数

redis.error_reply()和redis.status_reply()是两个辅助函数,分别用于返回Redis的错误回复以及状态回复:

redis.error_reply(error_message)
redis.status_reply(status_message)

redis.error_reply()函数会返回一个只包含err字段的Lua表格,而 err字段的值则是给定的错误消息;同样,redis.status_reply()函 数将返回一个只包含ok字段的Lua表格,而ok字段的值则是给定的状态 消息。

换句话说,调用:

redis.error_reply('something wrong')

将返回表格:

{err='something wrong'}

这个表格在redis-cli客户端中将被打印为以下输出:

redis> EVAL "return redis.error_reply('something wrong')" 0
(error) something wrong

而调用:

redis.status_reply('all is well')

将返回表格:

{ok='all is well'}

这个表格在redis-cli客户端中将被打印为以下输出:

redis> EVAL "return redis.status_reply('all is well')" 0
all is well

bit包

bit包可以对Lua脚本中的数字执行二进制按位操作,这个包从Redis 2.8.18版本开始可用。

bit包提供了将数字转换为十六进制字符串的tohex()函数,以及对 给定的数字执行按位反、按位或、按位并以及按位异或的bnot()、 bor()、band()、bxor()等函数:

bit.tohex(x [,n])
bit.bnot(x)
bit.bor(x1 [,x2...])
bit.band(x1 [,x2...])
bit.bxor(x1 [,x2...])

以下是一些bit包函数的使用示例:

redis> EVAL "return bit.tohex(65535)" 0
"0000ffff"
redis> EVAL "return bit.tohex(65535, 4)" 0
"ffff"
redis> EVAL "return bit.tohex(bit.bnot(0xFFFF))" 0
"ffff0000"
redis> EVAL "return bit.tohex(bit.bor(0xF00F, 0x0F00))" 0
"0000ff0f"

除了以上提到的函数之外,bit包还提供了其他按位操作函数,这些函 数以及它们的详细用法可以在bit包的文档上找到,网址为 http://bitop.luajit.org/api.html

struct包

struct包提供了能够在Lua值以及C结构之间进行转换的基本设施,这 个包提供了pack()、unpack()以及size()这3个函数:

struct.pack (fmt, v1, v2, ...)
struct.unpack (fmt, s, [i])
struct.size (fmt)

其中struct.pack()用于将给定的一个或多个Lua值打包为一个类结 构字符串(struct-like string),struct.unpack()用于从给定的 类结构字符串中解包出多个Lua值,而struct.size()则用于计算按 照给定格式进行打包需要耗费的字节数量。

以下是一个struct包的使用示例:

-- 打包一个浮点数、一个无符号长整数以及一个11字节长的字符串
redis> EVAL "return struct.pack('fLc11', 3.14, 10086, 'hello world')" 0
"\xc3\xf5H@f'\x00\x00\x00\x00\x00\x00hello world"
-- 计算打包需要耗费的字节数
redis> EVAL "return struct.size('fLc11')" 0
(integer) 23
-- 对给定的类结构字符串进行解包
redis> EVAL "return {struct.unpack('fLc11', ARGV[1])}" 0 "\xc3\xf5H@f'\x00\x00\x00\x00\x00\x00he
llo world"
1) (integer) 3 -- 根据Lua和Redis的转换规则,浮点数3.14被转换成了整数3
2) (integer) 10086
3) "hello world"
4) (integer) 24 -- 解包完成之后,程序在给定字符串中所处的索引

struct 包的文档详细地列出了打包以及解包的具体语法,网址为 http://www.inf.pucrio.br/~roberto/struct/

cjson包

cjson包能够为Lua脚本提供快速的JSON编码和解码操作,这个包中最 常用的就是将Lua值编码为JSON数据的编码函数encode(),以及将 JSON数据解码为Lua值的解码函数decode():

cjson.encode(value)
cjson.decode(json_text)

以下是一个使用cjson包进行编码和解码的示例:

redis> EVAL "return cjson.encode({true, 128, 'hello world'})" 0
"[true,128,\"hello world\"]"
redis> EVAL "return cjson.decode(ARGV[1])" 0 "[true,128,\"hello world\"]"
1) (integer) 1 -- 根据转换规则,Lua布尔值true被转换成了数字1
2) (integer) 128
3) "hello world"

除了encode()函数以及decode()函数之外,cjson包还提供了其他 函数,这些函数及其详细用法可以在cjson包的文档上找到,网址为 https://www.kyne.com.au/~mark/software/lua-cjson-manual.html

cmsgpack包

cmsgpack包能够为Lua脚本提供快速的MessagePack打包和解包操作, 这个包中最常用的就是打包函数pack()以及解包函数unpack(), 前者可以将给定的任意多个Lua值打包为msgpack包,而后者则可以将 给定的msgpack包解包为任意多个Lua值:

cmsgpack.pack(arg1, arg2, ..., argn)
cmsgpack.unpack(msgpack)

以下是一个使用这两个函数进行打包以及解包的示例:

redis> EVAL "return cmsgpack.pack({true, 128, 'hello world'})" 0
"\x93\xc3\xcc\x80\xabhello world"

redis> EVAL "return cmsgpack.unpack(ARGV[1])" 0 "\x93\xc3\xcc\x80\xabhello world"
1) (integer) 1 -- 根据转换规则,Lua布尔值true被转换成了数字1
2) (integer) 128
3) "hello world"

除了pack()函数以及unpack()函数之外,cmsgpack包还提供了其 他函数,这些函数及其详细用法可以在cmsgpack包的文档上找到,网 址为 https://github.com/antirez/lua-cmsgpack