memcached: 基于 cosocket API 的 nginx-module-lua 的 Lua memcached 客户端驱动
安装
如果您尚未设置 RPM 仓库订阅,请 注册。然后您可以继续以下步骤。
CentOS/RHEL 7 或 Amazon Linux 2
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-memcached
CentOS/RHEL 8+、Fedora Linux、Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-memcached
要在 NGINX 中使用此 Lua 库,请确保已安装 nginx-module-lua。
本文档描述了 lua-resty-memcached v0.17,于 2023 年 1 月 19 日发布。
此 Lua 库是 ngx_lua nginx 模块的 memcached 客户端驱动:
http://wiki.nginx.org/HttpLuaModule
此 Lua 库利用了 ngx_lua 的 cosocket API,确保 100% 非阻塞行为。
请注意,至少需要 ngx_lua 0.5.0rc29 或 OpenResty 1.0.15.7。
概述
server {
location /test {
content_by_lua '
local memcached = require "resty.memcached"
local memc, err = memcached:new()
if not memc then
ngx.say("failed to instantiate memc: ", err)
return
end
memc:set_timeout(1000) -- 1 sec
-- 或连接到一个由 memcached 服务器监听的 unix 域套接字文件:
-- local ok, err = memc:connect("unix:/path/to/memc.sock")
local ok, err = memc:connect("127.0.0.1", 11211)
if not ok then
ngx.say("failed to connect: ", err)
return
end
local ok, err = memc:flush_all()
if not ok then
ngx.say("failed to flush all: ", err)
return
end
local ok, err = memc:set("dog", 32)
if not ok then
ngx.say("failed to set dog: ", err)
return
end
local res, flags, err = memc:get("dog")
if err then
ngx.say("failed to get dog: ", err)
return
end
if not res then
ngx.say("dog not found")
return
end
ngx.say("dog: ", res)
-- 将其放入大小为 100 的连接池中,
-- 最大空闲超时为 10 秒
local ok, err = memc:set_keepalive(10000, 100)
if not ok then
ngx.say("cannot set keepalive: ", err)
return
end
-- 或立即关闭连接:
-- local ok, err = memc:close()
-- if not ok then
-- ngx.say("failed to close: ", err)
-- return
-- end
';
}
}
方法
在以下方法中提供的 key 参数将在发送到 memcached 服务器之前根据 URI 转义规则自动转义。
new
syntax: memc, err = memcached:new(opts?)
创建一个 memcached 对象。如果失败,则返回 nil 和描述错误的字符串。
它接受一个可选的 opts 表参数。支持以下选项:
-
key_transform一个数组表,包含两个函数,用于分别转义和反转义 memcached 键。默认情况下,memcached 键将作为 URI 组件进行转义和反转义,即
memached:new{
key_transform = { ngx.escape_uri, ngx.unescape_uri }
}
connect
syntax: ok, err = memc:connect(host, port)
syntax: ok, err = memc:connect("unix:/path/to/unix.sock")
尝试连接到 memcached 服务器正在监听的远程主机和端口,或连接到由 memcached 服务器监听的本地 unix 域套接字文件。
在实际解析主机名并连接到远程后端之前,此方法将始终查找连接池中由先前调用此方法创建的匹配空闲连接。
sslhandshake
syntax: session, err = memc:sslhandshake(reused_session?, server_name?, ssl_verify?, send_status_req?)
在当前建立的连接上执行 SSL/TLS 握手。有关更多详细信息,请参见 OpenResty 的 tcpsock.sslhandshake API。
set
syntax: ok, err = memc:set(key, value, exptime, flags)
无条件地将条目插入到 memcached 中。如果键已经存在,则覆盖它。
value 参数也可以是一个 Lua 表,包含多个 Lua 字符串,应该作为一个整体连接在一起(没有任何分隔符)。例如,
memc:set("dog", {"a ", {"kind of"}, " animal"})
在功能上等同于
memc:set("dog", "a kind of animal")
exptime 参数是可选的,默认为 0(表示永不过期)。过期时间以秒为单位。
flags 参数是可选的,默认为 0。
set_timeout
syntax: ok, err = memc:set_timeout(timeout)
设置后续操作的超时(以毫秒为单位),包括 connect 方法。
成功时返回 1,失败时返回 nil 和描述错误的字符串。
set_timeouts
syntax: ok, err = memc:set_timeouts(connect_timeout, send_timeout, read_timeout)
分别设置连接、发送和读取操作的超时(以毫秒为单位)。
成功时返回 1,失败时返回 nil 和描述错误的字符串。
set_keepalive
syntax: ok, err = memc:set_keepalive(max_idle_timeout, pool_size)
立即将当前 memcached 连接放入 ngx_lua cosocket 连接池中。
您可以指定连接在池中的最大空闲超时(以毫秒为单位)和每个 nginx 工作进程的池的最大大小。
成功时返回 1。出错时返回 nil 和描述错误的字符串。
仅在您本来会调用 close 方法的地方调用此方法。调用此方法将立即将当前 memcached 对象转为 closed 状态。对当前对象的任何后续操作(除了 connect())将返回 closed 错误。
get_reused_times
syntax: times, err = memc:get_reused_times()
此方法返回当前连接的(成功)重用次数。如果出错,则返回 nil 和描述错误的字符串。
如果当前连接不是来自内置连接池,则此方法始终返回 0,即连接从未被重用(尚未)。如果连接来自连接池,则返回值始终为非零。因此,此方法也可以用来确定当前连接是否来自池。
close
syntax: ok, err = memc:close()
关闭当前 memcached 连接并返回状态。
成功时返回 1。出错时返回 nil 和描述错误的字符串。
add
syntax: ok, err = memc:add(key, value, exptime, flags)
仅在键不存在时将条目插入到 memcached 中。
value 参数也可以是一个 Lua 表,包含多个 Lua 字符串,应该作为一个整体连接在一起(没有任何分隔符)。例如,
memc:add("dog", {"a ", {"kind of"}, " animal"})
在功能上等同于
memc:add("dog", "a kind of animal")
exptime 参数是可选的,默认为 0(表示永不过期)。过期时间以秒为单位。
flags 参数是可选的,默认为 0。
成功时返回 1。出错时返回 nil 和描述错误的字符串。
replace
syntax: ok, err = memc:replace(key, value, exptime, flags)
仅在键存在时将条目插入到 memcached 中。
value 参数也可以是一个 Lua 表,包含多个 Lua 字符串,应该作为一个整体连接在一起(没有任何分隔符)。例如,
memc:replace("dog", {"a ", {"kind of"}, " animal"})
在功能上等同于
memc:replace("dog", "a kind of animal")
exptime 参数是可选的,默认为 0(表示永不过期)。过期时间以秒为单位。
flags 参数是可选的,默认为 0。
成功时返回 1。出错时返回 nil 和描述错误的字符串。
append
syntax: ok, err = memc:append(key, value, exptime, flags)
将值附加到已经存在于 memcached 中的同一键的条目。
value 参数也可以是一个 Lua 表,包含多个 Lua 字符串,应该作为一个整体连接在一起(没有任何分隔符)。例如,
memc:append("dog", {"a ", {"kind of"}, " animal"})
在功能上等同于
memc:append("dog", "a kind of animal")
exptime 参数是可选的,默认为 0(表示永不过期)。过期时间以秒为单位。
flags 参数是可选的,默认为 0。
成功时返回 1。出错时返回 nil 和描述错误的字符串。
prepend
syntax: ok, err = memc:prepend(key, value, exptime, flags)
将值前置到已经存在于 memcached 中的同一键的条目。
value 参数也可以是一个 Lua 表,包含多个 Lua 字符串,应该作为一个整体连接在一起(没有任何分隔符)。例如,
memc:prepend("dog", {"a ", {"kind of"}, " animal"})
在功能上等同于
memc:prepend("dog", "a kind of animal")
exptime 参数是可选的,默认为 0(表示永不过期)。过期时间以秒为单位。
flags 参数是可选的,默认为 0。
成功时返回 1。出错时返回 nil 和描述错误的字符串。
get
syntax: value, flags, err = memc:get(key)
syntax: results, err = memc:get(keys)
通过单个键或键的表从 memcached 服务器获取单个条目或多个条目。
首先讨论键是单个字符串的情况。
如果找到条目且没有发生错误,则将返回键的值和关联的标志值。
如果发生错误,则 value 和 flags 将返回 nil,并且还将返回第三个(字符串)值以描述错误。
如果未找到条目,则将返回三个 nil 值。
然后讨论提供多个键的 Lua 表的情况。
在这种情况下,如果成功,将始终返回一个包含键-结果对的 Lua 表。每个值对应于表中的每个键,也是一个包含两个值的表,即键的值和键的标志。如果某个键不存在,则在 results 表中没有响应条目。
如果发生错误,将返回 nil,第二个返回值将是描述错误的字符串。
gets
syntax: value, flags, cas_unique, err = memc:gets(key)
syntax: results, err = memc:gets(keys)
与 get 方法类似,但还将返回与条目相关联的 CAS 唯一值,以及键的值和标志。
此方法通常与 cas 方法一起使用。
cas
syntax: ok, err = memc:cas(key, value, cas_unique, exptime?, flags?)
与 set 方法类似,但执行检查和设置操作,这意味着“存储此数据,但仅在我上次获取后没有其他人更新时。”
cas_unique 参数可以从 gets 方法中获得。
touch
syntax: ok, err = memc:touch(key, exptime)
更新现有键的过期时间。
成功时返回 1,失败时返回 nil 和描述错误的字符串。
此方法首次在 v0.11 版本中引入。
flush_all
syntax: ok, err = memc:flush_all(time?)
立即刷新(或使无效)memcached 服务器中所有现有条目(默认情况下)或在 time 参数指定的过期后(以秒为单位)。
成功时返回 1。出错时返回 nil 和描述错误的字符串。
delete
syntax: ok, err = memc:delete(key)
立即从 memcached 中删除键。
要删除的键必须已经存在于 memcached 中。
成功时返回 1。出错时返回 nil 和描述错误的字符串。
incr
syntax: new_value, err = memc:incr(key, delta)
将指定键的值按 delta 参数中指定的整数值递增。
成功时返回递增后的新值,失败时返回 nil 和描述错误的字符串。
decr
syntax: new_value, err = memc:decr(key, value)
将指定键的值按 delta 参数中指定的整数值递减。
成功时返回递减后的新值,失败时返回 nil 和描述错误的字符串。
stats
syntax: lines, err = memc:stats(args?)
返回 memcached 服务器的统计信息,带有可选的 args 参数。
成功时,此方法返回一个 Lua 表,包含所有输出行;失败时返回 nil 和描述错误的字符串。
如果省略 args 参数,则返回一般服务器统计信息。可能的 args 参数值包括 items、sizes、slabs 等。
quit
syntax: ok, err = memc:quit()
告诉服务器关闭当前 memcached 连接。
成功时返回 1,否则返回 nil。如果失败,还将返回另一个字符串值以描述错误。
通常,您可以直接调用 close 方法以实现相同的效果。
verbosity
syntax: ok, err = memc:verbosity(level)
设置 memcached 服务器使用的详细级别。level 参数应仅给出整数。
成功时返回 1,否则返回 nil。如果失败,还将返回另一个字符串值以描述错误。
init_pipeline
syntax: err = memc:init_pipeline(n?)
启用 Memcache 管道模式。所有后续对 Memcache 命令方法的调用将自动缓冲,并在调用 commit_pipeline 方法时一次性发送到服务器,或通过调用 cancel_pipeline 方法取消。
可选参数 n 是缓冲表的大小,默认值为 4。
commit_pipeline
syntax: results, err = memc:commit_pipeline()
通过将所有缓存的 Memcache 查询一次性提交到远程服务器,退出管道模式。这些查询的所有回复将自动收集,并作为一个大的多重回复在最高级别返回。
此方法成功时返回一个 Lua 表,失败时返回一个描述错误的 Lua 字符串。
cancel_pipeline
syntax: memc:cancel_pipeline()
通过丢弃自上次调用 init_pipeline 方法以来所有现有的缓冲 Memcache 命令,退出管道模式。
该方法没有返回值,总是成功。
自动错误日志记录
默认情况下,底层的 ngx_lua 模块在发生套接字错误时会进行错误日志记录。如果您已经在自己的 Lua 代码中进行了适当的错误处理,则建议通过关闭 ngx_lua 的 lua_socket_log_errors 指令来禁用此自动错误日志记录,即,
lua_socket_log_errors off;
限制
- 此库不能在
set_by_lua*、log_by_lua*和header_filter_by_lua*等代码上下文中使用,因为 ngx_lua cosocket API 不可用。 resty.memcached对象实例不能在 Lua 模块级别存储在 Lua 变量中,因为它将被同一 nginx 工作进程处理的所有并发请求共享(见 http://wiki.nginx.org/HttpLuaModule#Data_Sharing_within_an_Nginx_Worker),并在并发请求尝试使用相同的resty.memcached实例时导致不良的竞争条件。您应该始终在函数局部变量或ngx.ctx表中初始化resty.memcached对象。这些地方都有各自的数据副本,适用于每个请求。
另见
- ngx_lua 模块:http://wiki.nginx.org/HttpLuaModule
- memcached 有线协议规范:http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt
- lua-resty-redis 库。
- lua-resty-mysql 库。
GitHub
您可以在 nginx-module-memcached 的 GitHub 仓库 中找到此模块的其他配置提示和文档。