跳转至

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.0rc29OpenResty 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 服务器获取单个条目或多个条目。

首先讨论键是单个字符串的情况。

如果找到条目且没有发生错误,则将返回键的值和关联的标志值。

如果发生错误,则 valueflags 将返回 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 参数值包括 itemssizesslabs 等。

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_lualua_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 对象。这些地方都有各自的数据副本,适用于每个请求。

另见

GitHub

您可以在 nginx-module-memcached 的 GitHub 仓库 中找到此模块的其他配置提示和文档。