lua_shared_dict 通过 mmap 实现 worker 间共享内存,支持原子操作(如 incr)避免竞态,需在 http 块定义、合理预估大小(如限流 5m–20m),key 按维度设计(IP/Token/URI 等)并配合 TTL 自动清理。

直接用 lua_shared_dict 定义共享内存字典,就能在所有 Nginx worker 进程间同步连接计数和限流状态。它不是靠网络通信,而是靠操作系统 mmap 映射的一块共享内存区域,天然支持并发读写,关键操作(如 incr)底层加锁,避免竞态。
在 http 块中正确定义字典
必须放在 http{...} 块内,不能嵌套在 server 或 location 中:
- 每个字典名唯一,只允许字母、数字、下划线,大小写敏感
- 大小要预估合理:过小会触发 LRU 驱逐,过大浪费内存;例如限流常用 5m–20m,黑名单可用 2m 单独隔离
- 示例配置:
lua_shared_dict conn_counter 10m;
lua_shared_dict rate_limit 15m;
用原子操作做计数与判断
不要用 get + set 组合更新数值,否则在高并发下会出现“检查后失效”(check-then-act race)问题。比如两个请求同时读到值为 99,都执行 set(100),结果漏计一次。
- 计数递增必须用
dict:incr(key, 1),它是原子的 - 首次设置带 TTL:用
dict:add(key, init_val, ttl),避免覆盖已有值 - 检查超限后直接退出:
if newval > 100 then return ngx.exit(429) end
按维度构造 key 实现精准控制
key 设计决定限流粒度。常见做法有:
- IP 级:
"ip:" .. ngx.var.binary_remote_addr(推荐 binary_remote_addr,防伪造) - Token 级:
"token:" .. ngx.req.get_headers()["authorization"] - 接口路径级:
"uri:" .. ngx.var.uri - 组合维度:
"ip_uri:" .. ngx.var.binary_remote_addr .. ":" .. ngx.var.uri
配合 TTL 自动清理,减少手动维护
每个 key 可设秒级过期时间,后台惰性回收,不阻塞请求处理:
- 固定窗口限流:set key 初始值时指定 TTL,如
dict:set("ip:1.2.3.4", 0, 60) - 令牌桶模拟:用 incr 更新剩余令牌数,TTL 控制窗口周期
- 注意:TTL 不是精确到期,超时 key 在下次访问或后台扫描时才清除,不影响功能正确性











