lua-resty-lrucache

基于 LuaJIT FFI 的 Lua 端 LRU 缓存

$ opm get openresty/lua-resty-lrucache

名称

lua-resty-lrucache - 基于 LuaJIT FFI 的 Lua 端 LRU 缓存

状态

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

概要

    -- file myapp.lua: example "myapp" module
    
    local _M = {}
    
    -- alternatively: local lrucache = require "resty.lrucache.pureffi"
    local lrucache = require "resty.lrucache"
    
    -- we need to initialize the cache on the lua module level so that
    -- it can be shared by all the requests served by each nginx worker process:
    local c, err = lrucache.new(200)  -- allow up to 200 items in the cache
    if not c then
        return error("failed to create the cache: " .. (err or "unknown"))
    end
    
    function _M.go()
        c:set("dog", 32)
        c:set("cat", 56)
        ngx.say("dog: ", c:get("dog"))
        ngx.say("cat: ", c:get("cat"))
    
        c:set("dog", { age = 10 }, 0.1)  -- expire in 0.1 sec
        c:delete("dog")
    
        c:flush_all()  -- flush all the cached data
    end
    
    return _M


    # nginx.conf
    
    http {
        lua_package_path "/path/to/lua-resty-lrucache/lib/?.lua;;";
    
        server {
            listen 8080;
    
            location = /t {
                content_by_lua '
                    require("myapp").go()
                ';
            }
        }
    }

描述

此库为 OpenRestyngx_lua 模块实现了一个简单的 LRU 缓存。

此缓存还支持过期时间。

LRU 缓存完全驻留在 Lua VM 中,并且受 Lua GC 的影响。因此,不要期望它跨操作系统进程边界共享。好处是可以缓存任意复杂的 Lua 值(如深度嵌套的 Lua 表),而无需序列化开销(如使用 ngx_lua共享字典 API)。缺点是您的缓存始终局限于当前操作系统进程(如当前 nginx 工作进程)。在 init_by_lua 上下文中使用此库实际上没有意义,因为缓存不会被任何工作进程共享(除非您只想使用预定义的项“预热”缓存,这些项将通过 fork 被工作进程继承)。

此库包含两种不同的实现,以两种类的形式:resty.lrucacheresty.lrucache.pureffi。它们共享完全相同的 API。唯一的区别是后者是纯 FFI 实现,它还为缓存查找实现了基于 FFI 的哈希表,而前者则使用本机 Lua 表。

如果缓存命中率相对较高,则应使用 resty.lrucache 类,它比 resty.lrucache.pureffi 更快。

但是,如果缓存命中率相对较低,并且插入到缓存中和从缓存中删除的键可能存在大量的变化,那么您应该使用 resty.lrucache.pureffi,因为 Lua 表在设计上不擅长频繁删除键,并且您会看到 LuaJIT 运行时中的 resizetab 函数调用在 CPU 上的火焰图 中非常热,如果您在这种情况下使用 resty.lrucache 类而不是 resty.lrucache.pureffi

方法

要加载此库,

  1. 您需要在 ngx_lua 的 lua_package_path 指令中指定此库的路径。例如,lua_package_path "/path/to/lua-resty-lrucache/lib/?.lua;;";

  2. 您使用 require 将库加载到本地 Lua 变量中

        local lrucache = require "resty.lrucache"

        local lrucache = require "resty.lrucache.pureffi"

new

语法:cache, err = lrucache.new(max_items [, load_factor])

创建一个新的缓存实例。如果失败,则返回 nil 和描述错误的字符串。

max_items 参数指定缓存中保存的最大项目数。

load-factor 参数指定 resty.lrucache.pureffi 内部使用的基于 FFI 的哈希表的“负载因子”;默认值为 0.5(即 50%);如果指定负载因子,它将被限制在 [0.1, 1] 范围内(即如果负载因子大于 1,它将饱和到 1;同样,如果负载因子小于 0.1,它将被限制到 0.1)。此参数仅对 resty.lrucache.pureffi 有意义。

set

语法:cache:set(key, value, ttl)

设置一个带有值和过期时间的键。

ttl 参数指定过期时间段。时间值以秒为单位,但您也可以指定小数部分,如 0.25ttl 参数值为 nil 表示永远不会过期(这是默认值)。

当缓存已满时,缓存将自动驱逐最不常使用的项目。

get

语法:data, stale_data = cache:get(key)

使用键获取值。如果键在缓存中不存在或已过期,则将返回 nil 值。

v0.03 开始,如果可用,陈旧数据也将作为第二个返回值返回。

delete

语法:cache:delete(key)

从缓存中删除由键指定的项目。

flush_all

语法:cache:flush_all(key)

刷新当前缓存实例中所有现有数据(如果有)。这是一个 O(1) 操作,应该比创建全新的缓存实例快得多。

注意:resty.lrucache.pureffiflush_all() 方法是一个 O(n) 操作。

先决条件

安装

建议直接使用最新的 OpenResty 包。至少需要 OpenResty 1.4.2.9。在构建 OpenResty 包时,您需要通过将 --with-luajit 选项传递给其 ./configure 脚本来启用 LuaJIT。不需要额外的 Nginx 配置。

如果您想将此库与您自己的 Nginx 构建(使用 ngx_lua)一起使用,那么您需要确保您至少使用的是 ngx_lua 0.8.10。

此外,您需要配置 lua_package_path 指令,将您的 lua-resty-lrucache 源代码树的路径添加到 ngx_lua 的 Lua 模块搜索路径中,如下所示

        # nginx.conf
        http {
            lua_package_path "/path/to/lua-resty-lrucache/lib/?.lua;;";
            ...
        }

然后在 Lua 中加载库

        local lrucache = require "resty.lrucache"

待办事项

  • 添加新的方法 get_stale 用于获取已过期的项目。

社区

英文邮件列表

The openresty-en 邮件列表适用于英语使用者。

中文邮件列表

The openresty 邮件列表适用于中文使用者。

错误和补丁

请通过以下方式报告错误或提交补丁

  1. GitHub 问题跟踪器 上创建工单,

  2. 或发布到 "OpenResty 社区" 中。

作者

Yichun "agentzh" Zhang (章亦春) <[email protected]>,OpenResty Inc.

Shuxin Yang.

版权和许可

此模块在 BSD 许可下发布。

版权所有 (C) 2014-2018,由 Yichun "agentzh" Zhang,OpenResty Inc.

版权所有 (C) 2014-2017,由 Shuxin Yang。

保留所有权利。

只要满足以下条件,就可以在源代码和二进制形式中重新分发和使用此软件,无论是否修改。

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

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

本软件由版权所有者和贡献者“按现状”提供,任何明示或暗示的保证,包括但不限于适销性和特定用途适用性的暗示保证均被免除。在任何情况下,版权所有者或贡献者都不对因使用本软件而引起的任何直接、间接、偶然、特殊、示范性或后果性损害(包括但不限于替代商品或服务的采购;使用、数据或利润损失;或业务中断)负责,无论任何责任理论,无论是基于合同、严格责任或侵权(包括疏忽或其他原因)而产生的,即使已告知存在此类损害的可能性。

另请参阅

  • ngx_lua 模块:https://github.com/chaoslawful/lua-nginx-module

  • OpenResty:https://openresty.org.cn

作者

Yichun Zhang (agentzh)

许可证

2bsd

依赖关系

luajit

版本