lua-resty-memcached

基于 cosocket API 的 ngx_lua Lua memcached 客户端驱动

$ opm get openresty/lua-resty-memcached

名称

lua-resty-memcached - 基于 cosocket API 的 ngx_lua Lua memcached 客户端驱动

此库被认为是生产就绪的。

描述

此 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

概要

        lua_package_path "/path/to/lua-resty-memcached/lib/?.lua;;";
    
        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
    
                    -- or connect to a unix domain socket file listened
                    -- by a memcached server:
                    --     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)
    
                    -- put it into the connection pool of size 100,
                    -- with 10 seconds max idle timeout
                    local ok, err = memc:set_keepalive(10000, 100)
                    if not ok then
                        ngx.say("cannot set keepalive: ", err)
                        return
                    end
    
                    -- or just close the connection right away:
                    -- local ok, err = memc:close()
                    -- if not ok then
                    --     ngx.say("failed to close: ", err)
                    --     return
                    -- end
                ';
            }
        }

方法

以下方法中提供的 key 参数将在发送到 memcached 服务器之前根据 URI 转义规则自动转义。

new

语法:memc, err = memcached:new(opts?)

创建一个 memcached 对象。如果失败,则返回 nil 和描述错误的字符串。

它接受一个可选的 opts 表格参数。支持以下选项

  • key_transform

    包含两个函数的数组表格,分别用于转义和取消转义 memcached 键。默认情况下,memcached 键将作为 URI 组件转义和取消转义,即

        memached:new{
            key_transform = { ngx.escape_uri, ngx.unescape_uri }
        }

connect

语法:ok, err = memc:connect(host, port)

语法:ok, err = memc:connect("unix:/path/to/unix.sock")

尝试连接到 memcached 服务器正在监听的远程主机和端口或 memcached 服务器监听的本地 unix 域套接字文件。

在实际解析主机名并连接到远程后端之前,此方法将始终查找连接池以匹配此方法先前调用创建的空闲连接。

set

语法: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

语法:ok, err = memc:set_timeout(time)

为后续操作(包括 connect 方法)设置超时(以毫秒为单位)保护。

成功时返回 1,否则返回 nil 和描述错误的字符串。

set_keepalive

语法: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

语法:times, err = memc:get_reused_times()

此方法返回当前连接的(成功)重用次数。如果发生错误,它将返回 nil 和描述错误的字符串。

如果当前连接不是来自内置连接池,那么此方法始终返回 0,也就是说,连接从未被重用(尚未)。如果连接来自连接池,则返回值始终非零。因此,此方法也可以用于确定当前连接是否来自池。

close

语法:ok, err = memc:close()

关闭当前 memcached 连接并返回状态。

成功时返回 1。如果发生错误,则返回 nil 和描述错误的字符串。

add

语法: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

语法: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

语法: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

语法: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

语法:value, flags, err = memc:get(key) 语法:results, err = memc:get(keys)

通过单个键或键的表格获取 memcached 服务器中的单个条目或多个条目。

让我们首先讨论当键是单个字符串的情况。

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

如果发生错误,则 valueflags 将被转换为 nil 值,并且还将返回第三个(字符串)值来描述错误。

如果未找到条目,则将返回三个 nil 值。

然后让我们讨论当提供多个键的 Lua 表格时的情况。

在这种情况下,如果成功,将始终返回一个包含键结果对的 Lua 表格。表格中每个键对应的值也是一个包含两个值的表格,即键的值和键的标志。如果键不存在,则 results 表格中没有响应条目。

如果发生错误,将返回 nil,并且第二个返回值将是描述错误的字符串。

gets

语法:value, flags, cas_unique, err = memc:gets(key)

语法:results, err = memc:gets(keys)

就像 get 方法一样,但除了键的值和标志外,还会返回与条目关联的 CAS 唯一值。

此方法通常与 cas 方法一起使用。

cas

语法:ok, err = memc:cas(key, value, cas_unique, exptime?, flags?)

就像 set 方法一样,但执行检查和设置操作,这意味着“存储此数据,但前提是自上次获取以来没有人更新过它”。

cas_unique 参数可以从 gets 方法中获得。

touch

语法:ok, err = memc:touch(key, exptime)

更新现有键的到期时间。

成功时返回 1,否则返回 nil 和描述错误的字符串。

此方法是在 v0.11 版本中首次引入的。

flush_all

语法:ok, err = memc:flush_all(time?)

立即(默认)或在 time 参数(以秒为单位)指定的到期时间后,刷新(或使无效)memcached 服务器中的所有现有条目。

成功时返回 1。如果发生错误,则返回 nil 和描述错误的字符串。

delete

语法:ok, err = memc:delete(key)

立即从 memcached 中删除键。

要删除的键必须已存在于 memcached 中。

成功时返回 1。如果发生错误,则返回 nil 和描述错误的字符串。

incr

语法:new_value, err = memc:incr(key, delta)

将指定键的值增加 delta 参数中指定的整数值。

成功时返回递增后的新值,如果失败,则返回 nil 和描述错误的字符串。

decr

语法:new_value, err = memc:decr(key, value)

将指定键的值减少 delta 参数中指定的整数值。

成功时返回递减后的新值,如果失败,则返回 nil 和描述错误的字符串。

stats

语法:lines, err = memc:stats(args?)

返回 memcached 服务器统计信息,带有可选的 args 参数。

如果成功,此方法将返回一个包含所有输出行的 lua 表格;如果失败,它将返回 nil 和描述错误的字符串。

如果省略 args 参数,则将返回一般的服务器统计信息。可能的 args 参数值包括 itemssizesslabs 等。

version

语法:version, err = memc:version(args?)

返回服务器版本号,例如 1.2.8

如果发生错误,它将返回 nil 和描述错误的字符串。

quit

语法:ok, err = memc:quit()

告诉服务器关闭当前 memcached 连接。

成功时返回 1,否则返回 nil。如果发生错误,还将返回另一个字符串值来描述错误。

通常,您可以直接调用 close 方法来达到相同的效果。

verbosity

语法:ok, err = memc:verbosity(level)

设置 memcached 服务器使用的详细程度级别。level 参数应仅给出整数。

成功时返回 1,否则返回 nil。如果发生错误,还将返回另一个字符串值来描述错误。

自动错误日志记录

默认情况下,底层的 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 对象。这些地方对每个请求都有自己的数据副本。

待办事项

  • 实现 memcached 管道 API。

  • 实现 memcached ascii 协议的 UDP 部分。

作者

Yichun "agentzh" Zhang (章亦春) <agentzh@gmail.com>, CloudFlare Inc.

版权和许可

此模块根据 BSD 许可证授权。

版权所有 (C) 2012-2016,作者 Yichun "agentzh" Zhang (章亦春) <agentzh@gmail.com>, CloudFlare Inc.

保留所有权利。

在满足以下条件的情况下,允许以源代码和二进制形式重新分发和使用此软件,无论是否修改:

  • 源代码的重新分发必须保留上述版权声明、此条件列表和以下免责声明。

  • 二进制形式的重新分发必须在随发行版提供的文档和/或其他材料中复制上述版权声明、此条件列表和以下免责声明。

此软件由版权所有者和贡献者“按原样”提供,任何明示或暗示的保证,包括但不限于对适销性和特定用途适用性的暗示保证均予以否认。在任何情况下,版权所有者或贡献者均不对任何直接的、间接的、偶然的、特殊的、惩罚性的或后果性的损害负责(包括但不限于替代商品或服务的采购;使用、数据或利润损失;或业务中断),无论其原因如何以及在任何责任理论下,无论是合同、严格责任或侵权行为(包括疏忽或其他原因),均与本软件的使用有关,即使已告知可能会发生此类损害。

另请参见

  • 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 库。

作者

张逸淳 "agentzh" (agentzh)

许可证

2bsd

版本