一 概述
shdict api 实现了共享内存的操作接口,在 lua-nginx 模块中将所有的共享内存(shm_zone)存储在一个 Table 中,每个 shm_zone 使用红黑树存储操作的 key-value。刚才说所有的共享内存,准确的说应该是所有使用 lua_shared_dict 指令创建的共享内存。
lua-nginx 模块中每个 shm_zone 用 Table 表示,在表中使用 SHDICT_USERDATA_INDEX 索引每个共享内存的 zone。
1 | void |
二 接口
1. get|get_stale
1 | value, flags = ngx.shared.DICT:get(key) |
get 函数用来从共享内存中获得 key 对应的值,如果 key 不存在或者已经过期则返回 nil。出错时返回 nil 以及错误描述字符串。
get_stale 函数与 get 相同,唯一不同点在于使用 get_stale 函数访问过期的 key-value 时返回其原始值,而非 nil。同时,返回值中 stale 标识 key 是否已经过期。
**key 必须为字符串类型,value 可以为字符串、数值、布尔或者 NIL**。
get、get_stale 函数最终都是有 ngx_http_lua_shdict_get_helper 实现,只是 get 调用时 get_stale 为 0,get_stale 调用时值为 1。ngx_http_lua_shdict_get_helper 函数实现:
1 | static int |
2. set
1 | success, err, forcible = ngx.shared.DICT:set(key, value, exptime?, flags?) |
无条件的向共享内存中添加一条 key-value。返回值 success 用以标明添加是否成功,err 为错误描述字符串,布尔类型的 forcible 用来标明为了保存本条记录是否将其他合法的 key-value 删除。
参数 key、value 是要保存的 key-value,可选的数值参数 exptime 指定 key 的过期时间,单位为秒但是可以使用小数精确到毫秒级别。exptime 默认为 0,不过期。可选的参数 flag 为 key 的“用户”表示,在使用 get|get_stale 获取 key 时会返回 flag。flag 是 32 为的整数。
在调用 set 时,如果共享内存已经无可用空间,会使用 LRU 策略,从 lru_queue 中删除 key-value(仍然有可能无法满足 set 调用使用的空间)。set 实现函数为 ngx_http_lua_shdict_set_helper,实现函数:
1 | // flag 控制 set 的行为,以实现 set、safe_set 功能 |
ngx_http_lua_shdict_set_helper 函数实现了新增、更新、删除功能,逻辑非常复杂。
3. safe_set
1 | ok, err = ngx.shared.DICT:safe_set(key, value, exptime?, flags?) |
与 set 方法相同,只不过不会删除未过期 key-value 以满足保存操作。
4. add
1 | success, err, forcible = ngx.shared.DICT:add(key, value, exptime?, flags?) |
与 set 方法相似,不过只会在共享内存中不存在 key 时才会保存设置的 key-value。如果 key 已经在共享内存中,success 为 false,err 为 exists。有可能会删除未过期 key-value,以满足存储需求。
5. safe_add
1 | ok, err = ngx.shared.DICT:safe_add(key, value, exptime?, flags?) |
与 add 方法类似,不过不会删除未过期的 key-value 以满足存储需求。
6. replace
1 | success, err, forcible = ngx.shared.DICT:replace(key, value, exptime?, flags?) |
与 set 方法类似,不过仅当 key 已经存在于共享内存时才会进行保存操作。如果 key 不存在时会返回 not found 错误描述字符串。
7. incr
1 | newval, err, forcible? = ngx.shared.DICT:incr(key, value, init?, init_ttl?) |
将 key 指定的数值类型值增加 value 步长,返回增加后的 value。如果 key 在共享内存中未找到,init 可选参数影响其行为:
init为nil,函数返回nil,并且错误描述为not found。init为数值参数,函数返回init + value。
与 add 函数类似,如果存储空间不足,会删除未过期 key-value。
可选参数 init_ttl 控制 key 的超时时间(仅在初始化时参数有效),以秒为单位,支持浮点数可以精确到毫秒。
8. delete
1 | ngx.shared.DICT:delete(key) |
无条件的删除 key 指定的 key-value,等价于调用 set(key, nil) 函数。
9. lpush
1 | length, err = ngx.shared.DICT:lpush(key, value) |
将指定的数值或字符串 value 插入基于共享内存的列表头,返回 list 中的元素数量。如果 key 不存在,则在执行当前函后会创建一个新的列表,当 key 已经存在但是非列表类型,错误提示为 value not a list。
**lpush 不会删除未过期 key-value**。
10. rpush
1 | length, err = ngx.shared.DICT:rpush(key, value) |
与 lpush 相似,只不过 rpush 在队列尾插入值。
11. lpop
1 | val, err = ngx.shared.DICT:lpop(key) |
从 list 中返回并删除首个元素,如果 key 不存在返回 nil,如果 key 相应的 value 非 list 类型,返回 value not a list。
12. rpop
1 | val, err = ngx.shared.DICT:rpop(key) |
从 list 中返回并删除末尾元素,如果 key 不存在返回 nil,如果 key 相应的 value 非 list 类型,返回 value not a list。
13. llen
1 | len, err = ngx.shared.DICT:llen(key) |
计算 list 中元素数量,如果 key 不存在代表是空列表,返回 0。如果 key 的值非列表类型,返回 nil 以及相应错误描述。
14. ttl
1 | ttl, err = ngx.shared.DICT:ttl(key) |
返回 key 剩余的 TTL 时间,以秒为单位,精确到毫秒。失败返回 nil 以及错误描述字符串。如果返回 ttl 为零,说明未设置超时时间。
15. expire
1 | success, err = ngx.shared.DICT:expire(key, exptime) |
更新 key 的超时时间,返回布尔类型状态信息以及错误描述。参数 exptime 以秒为单位精确到毫秒。
16. flush_all|flush_expired
1 | ngx.shared.DICT:flush_all() |
删除所有的 key-value 或者过期的 key-value。flush_expired 函数接受一个可选的 max_count 参数,用来控制删除过期 key 数量。默认为 0,会删除所有的过期 key。同时,flush_expired 函数会返回删除的 key 数量。
17. get_keys
1 | keys = ngx.shared.DICT:get_keys(max_count?) |
返回一个包含共享内存(shm_zone)所有 keys 的 Array Table。可选数值参数 max_count 可以控制返回的 key 数量,默认为 1024 个。