摘自:http://www.daileinote.com/computer/openresty/11
通过 lua_shared_dict 指令可以声明一个共享内存区域,可以在多个 worker 进程间共享,单位支持 k、m,然后配合 ngx.shared.DICT api函数来操作。nginx -s reload 后共享内存的数据还在。
这个共享内存功能非常有用,极大的便利了worker 进程间的通信和协作,而且还提供了类似 redis 的数据结构,可以当做一个简易的数据库,而且没有通信开销。
共享内存在 Openresty 里用途很广,基于它可以实现流量统计、缓存、进程锁等高级功能。
1 | http { |
下面将介绍一些操作共享内存的函数,这些函数都是原子操作,只要在同一个内存区域,在多个worker 进程间并发都是安全的。
ngx.shared.DICT.set
1 | syntax: success, err, forcible = ngx.shared.DICT:set(key, value, exptime?, flags?) |
无条件设置一个共享内存的值,返回3个值:
success:布尔值,是否成功
err:错误信息
forcible:布尔值,是否由于内存不足把其他有效的值挤出去了
value 值可以是 布尔值、数字、字符串、nil,同过get返回的保留这些类型。
exptime 可选值用来设置过期时间(秒),精度为 0.001s。默认值 0 代表不过期。
flags 可选值,一个标记,无符号32位整形,默认为0,通过 get 也可以返回。
当内存不够分配,那么会强制移除最老的项根据过期时间排序,如果移除了还是由于某种原因不能新增数据,那么 success 为fasle,错误信息存入 err。
1 | local cats = ngx.shared.cats |
也可以是下面这种方式
1 | local cats = ngx.shared.cats |
ngx.shared.DICT.safe_set
1 | syntax: ok, err = ngx.shared.DICT:safe_set(key, value, exptime?, flags?) |
同上,只是当内存不足时不会强制移除没过期的项目来腾出空间,直接返回 nil 和 错误信息。
ngx.shared.DICT.add
1 | syntax: success, err, forcible = ngx.shared.DICT:add(key, value, exptime?, flags?) |
同 ngx.shared.DICT.set,只是如果 key 已经存在且没过期,返回 fasle,err 设置为 "exists"。
ngx.shared.DICT.safe_add
1 | syntax: ok, err = ngx.shared.DICT:safe_add(key, value, exptime?, flags?) |
同上,只是当内存不足时不会强制移除没过期的项目来腾出空间,直接返回 nil 和 错误信息。
ngx.shared.DICT.get
1 | syntax: value, flags = ngx.shared.DICT:get(key) |
获取共享内存的值,如果 key 不存在或者过期,返回 nil。出错返回 nil 和 错误信息。
1 | local sh_dog = ngx.shared.dogs |
另一种获取方式
1 | local sh_dog = ngx.shared.dogs |
ngx.shared.DICT.get_stale
1 | syntax: value, flags, stale = ngx.shared.DICT:get_stale(key) |
同上,就算过期了也返回(只要没清除)。stale 代表是否过期了。
ngx.shared.DICT.replace
1 | syntax: success, err, forcible = ngx.shared.DICT:replace(key, value, exptime?, flags?) |
类似 set,只是 key 必须存在且没过期才会替换成功,否则返回 false,err为 "not found"。
ngx.shared.DICT.delete
1 | syntax: ngx.shared.DICT:delete(key) |
无条件删除,等同于
1 | ngx.shared.DICT:set(key, nil) |
ngx.shared.DICT.incr
1 | syntax: newval, err, forcible? = ngx.shared.DICT:incr(key, value, init?, init_ttl?) |
将 key 里面的数字值增加 value,并返回增加后的数值。value 和 init 可以是正负整数,正负浮点数。
如果 key 里面原来的值不是数字,返回 nil,err设置为 "not a number"。
如果 key 不存在或者过期:
1.如果提供了 init,那么将会新增 key,并初始化值为 init+value,如果内存不足,还是会挤掉最老的值,如果挤掉了,那么 forcible 就为 true。init_ttl 代表新增的 key 的过期时间,默认为 0,不过期。
2.如果没提供,返回 nil,err设置为 "not found"。
操作列表
ngx.shared.DICT.lpush
1 | syntax: length, err = ngx.shared.DICT:lpush(key, value) |
从key对应的列表的最左边插入 value,返回插入后列表的元素个数。如果内存不足,直接返回 nil,err设置为 "no memory"。
如果 key 不存在,那么会新建空列表后再插入,如果 key 已经存在但是不是列表,返回 nil,err为 "value not a list"。
ngx.shared.DICT.rpush
1 | syntax: length, err = ngx.shared.DICT:rpush(key, value) |
同上,只是从右边插入。
ngx.shared.DICT.lpop
1 | syntax: val, err = ngx.shared.DICT:lpop(key) |
移除由key指定的列表最左边的值并返回,key 不存在返回 nil,key存在但是不是列表,返回nil,err为 "value not a list"。
ngx.shared.DICT.rpop
1 | syntax: val, err = ngx.shared.DICT:rpop(key) |
同上,只是从右边移除。
ngx.shared.DICT.llen
1 | syntax: len, err = ngx.shared.DICT:llen(key) |
返回指定 key 列表的元素个数,key 不存在返回0,存在但是不是列表返回 nil,err 为 "value not a list"。
ngx.shared.DICT.ttl
1 | syntax: ttl, err = ngx.shared.DICT:ttl(key) |
返回指定 key 的过期时间(秒),精度为 0.001,返回 0 代表永不过期。如果 key 不存在或者过期,返回 nil,err为 "not found"。
1 | lua_shared_dict dogs 10m; |
ngx.shared.DICT.expire
1 | syntax: success, err = ngx.shared.DICT:expire(key, exptime) |
更新 key 的过期时间单位秒,精度0.001,0代表永不过期。如果 key 不存在返回 nil,err为 "not found"。
ngx.shared.DICT.flush_all
1 | syntax: ngx.shared.DICT:flush_all() |
标记所有的key为过期。
ngx.shared.DICT.flush_expired
1 | syntax: flushed = ngx.shared.DICT:flush_expired(max_count?) |
将过期的key删除并释放内存,max_count 限制删除的数量,默认为0,代表不限制。
ngx.shared.DICT.get_keys
1 | syntax: keys = ngx.shared.DICT:get_keys(max_count?) |
从字典里获取key,默认只会返回前 1024 个,如果指定了 max_count,那么返回 max_count 个,如果 max_count 为0,返回全部。
注意:因为该操作会锁住共享内存,如果 key 很多不建议使用该函数,因为会让需要用到该共享内存的 worker 进程阻塞。
ngx.shared.DICT.capacity
1 | syntax: capacity_bytes = ngx.shared.DICT:capacity() |
返回共享内存的容量(由 lua_shared_dict 指定),单位字节。
ngx.shared.DICT.free_space
1 | syntax: free_page_bytes = ngx.shared.DICT:free_space() |
获取共享内存的空闲空间,由于内部 nginx 是用 slab 分配器分配的内存,返回0可能还是有空间来存储新的值。
简单的例子
1 | lua_shared_dict dogs 10m; |
