- 新增 lua-embed-analysis.md 技术分析文档 - 新增 lua-nginx-module 文档目录 - 更新 gitignore 允许跟踪 docs/lua-nginx-module/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6.2 KiB
6.2 KiB
lua-nginx-module 共享内存字典 (shdict)
本文档详细说明 lua-nginx-module 的共享内存字典功能。
一、核心文件
| 文件 | 说明 |
|---|---|
src/ngx_http_lua_shdict.c |
shdict 核心实现 |
src/ngx_http_lua_shdict.h |
数据结构定义 |
src/ngx_http_lua_directive.c |
配置指令处理 |
二、数据结构
2.1 节点结构
typedef struct {
u_char color; /* 红黑树颜色 */
uint8_t value_type; /* 值类型 */
u_short key_len; /* key 长度 */
uint32_t value_len; /* value 长度 */
uint64_t expires; /* 过期时间 (毫秒) */
ngx_queue_t queue; /* LRU 队列节点 */
uint32_t user_flags; /* 用户自定义标志 */
u_char data[1]; /* key + value 数据 */
} ngx_http_lua_shdict_node_t;
2.2 值类型枚举
enum {
SHDICT_TNIL = 0, /* 空值 */
SHDICT_TBOOLEAN = 1, /* 布尔值 */
SHDICT_TNUMBER = 3, /* 数字 */
SHDICT_TSTRING = 4, /* 字符串 */
SHDICT_TLIST = 5, /* 列表 */
};
2.3 共享上下文
typedef struct {
ngx_rbtree_t rbtree; /* 红黑树根 */
ngx_rbtree_node_t sentinel; /* 红黑树哨兵 */
ngx_queue_t lru_queue; /* LRU 队列头 */
} ngx_http_lua_shdict_shctx_t;
typedef struct {
ngx_http_lua_shdict_shctx_t *sh; /* 共享上下文 */
ngx_slab_pool_t *shpool; /* slab 分配器 */
ngx_str_t name; /* 字典名称 */
} ngx_http_lua_shdict_ctx_t;
三、配置
lua_shared_dict <name> <size>
定义共享内存字典。
- 参数:
name: 字典名称size: 内存大小 (最小 8KB)
- 配置层级: main
- 示例:
lua_shared_dict cache 10m; lua_shared_dict sessions 100m; lua_shared_dict counters 1m;
四、Lua API
4.1 获取字典对象
local dict = ngx.shared.cache
4.2 基础操作
dict:get(key)
获取值。
- 参数:
key(string) - 返回值: value, err 或 nil
- 示例:
local val, err = ngx.shared.cache:get("user:123") if val == nil and err then ngx.log(ngx.ERR, "get failed: ", err) end
dict:get_stale(key)
获取值(允许过期数据)。
dict:set(key, value, exptime?, flags?)
设置值。
- 参数:
key(string)value(string/number/boolean/nil)exptime(number, 可选): 过期时间秒数flags(number, 可选): 用户标志
- 返回值: success, err, forcible
- 示例:
local dict = ngx.shared.cache local ok, err, forcible = dict:set("key", "value", 60) if forcible then ngx.log(ngx.WARN, "forced to evict old items") end
dict:safe_set(key, value, exptime?, flags?)
安全设置值(不会淘汰有效项)。
dict:add(key, value, exptime?, flags?)
仅在 key 不存在时添加。
dict:safe_add(key, value, exptime?, flags?)
安全添加(不会淘汰有效项)。
dict:replace(key, value, exptime?, flags?)
仅在 key 存在时替换。
dict:delete(key)
删除 key。
4.3 数值操作
dict:incr(key, value, init?)
原子递增。
- 参数:
key(string)value(number): 增量init(number, 可选): key 不存在时的初始值
- 返回值: new_value, err 或 nil
- 示例:
local dict = ngx.shared.counters local new_val, err = dict:incr("hits", 1, 0) ngx.say("Hits: ", new_val)
4.4 列表操作
dict:lpush(key, value)
左侧推入列表。
dict:rpush(key, value)
右侧推入列表。
dict:lpop(key)
左侧弹出列表。
dict:rpop(key)
右侧弹出列表。
dict:llen(key)
获取列表长度。
- 示例:
local dict = ngx.shared.queue dict:rpush("jobs", "job1") dict:rpush("jobs", "job2") local job = dict:lpop("jobs") -- "job1" local len = dict:llen("jobs") -- 1
4.5 过期管理
dict:ttl(key)
获取剩余 TTL。
- 返回值: ttl, err 或 nil
dict:expire(key, exptime)
设置过期时间。
- 参数:
key(string)exptime(number): 秒数
- 返回值: success, err
dict:flush_all()
标记所有项为过期。
dict:flush_expired(max_count?)
清除过期项。
- 参数:
max_count(number, 可选)
4.6 容量信息
dict:capacity()
获取总容量。
- 返回值: number (bytes)
dict:free_space()
获取空闲空间。
- 返回值: number (bytes)
dict:get_keys(max_count?)
获取所有 key。
- 参数:
max_count(number, 可选, 默认 1024) - 返回值: table of keys
五、内部实现
5.1 Slab 分配器
使用 Nginx 的 slab 分配器管理共享内存:
ngx_slab_alloc_locked()/ngx_slab_alloc()ngx_slab_free_locked()/ngx_slab_free()
5.2 红黑树索引
用于快速查找:
- Key 哈希 → 红黑树节点
- 冲突处理:
ngx_memn2cmp比较实际 key
5.3 LRU 队列
实现最近最少使用淘汰:
- 新访问项移到队列头
- 淘汰时从队列尾移除
5.4 并发控制
使用互斥锁保护共享数据:
ngx_shmtx_lock(&ctx->shpool->mutex);
// 操作共享数据
ngx_shmtx_unlock(&ctx->shpool->mutex);
六、使用示例
6.1 简单缓存
local function get_with_cache(key, fetch_func, ttl)
local dict = ngx.shared.cache
local value = dict:get(key)
if value then
return value
end
value = fetch_func()
dict:set(key, value, ttl)
return value
end
6.2 分布式锁
local function acquire_lock(lock_name, timeout, expiry)
local dict = ngx.shared.locks
local ok, err = dict:add(lock_name, 1, expiry)
if ok then
return true
end
return false, err
end
local function release_lock(lock_name)
local dict = ngx.shared.locks
dict:delete(lock_name)
end
6.3 限流计数
local function rate_limit(key, limit, window)
local dict = ngx.shared.limits
local count, err = dict:incr(key, 1, 0, window)
if count > limit then
return false -- 超限
end
return true
end