Nginx共享内存zone由master调用mmap()创建并fork继承,所有worker直接映射同一物理内存,读写零拷贝、毫秒级响应;zone需显式声明大小与名称,内部采用哈希表/红黑树+slab分配器组织,关键字段用原子操作保障安全。

nginx 的共享内存 zone 不是“多个进程各自存一份”,而是 master 进程调用 mmap() 创建一块物理内存,所有 worker 进程通过 fork 自动继承、直接映射访问——读写零拷贝、无序列化、毫秒级响应。
zone 是怎么创建和共享的
master 进程在启动时统一调用 ngx_shm_alloc()(封装自 mmap())分配一块连续内存,并记录起始地址、大小和名称;worker 进程 fork 后自动获得该内存的映射权限,无需重新分配或通信。整个过程不依赖磁盘文件,也不走 socket 或消息队列。
- 每个 zone 必须显式声明,例如
limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=5r/s - 名字(如
ip_limit)用于内部索引,大小(如10m)需预估并留余量,过小会触发 LRU 驱逐 - reload 操作会清空 zone 内容(除非配置未变更且使用
nginx -s reload的特定行为)
数据结构与并发安全设计
zone 内部不是裸内存,而是由 Nginx 自定义组织:常用哈希表或红黑树索引 key(如 IP、URI),底层用 slab 分配器管理 slot,关键字段(如计数器、时间戳)使用 ngx_atomic_t 类型。
- 支持原子增减(
ngx_atomic_fetch_add)、CAS(ngx_atomic_cmp_set),但仅限特定字段 - 不提供任意结构体的原子读-改-写,复杂逻辑靠“本地缓存 + 周期合并”降低竞争
- SSL session 缓存用原子指针操作更新 LRU 头指针,避免锁;upstream 状态位以只读方式映射,worker 定期轮询
典型应用中的协同模式
不同模块利用 zone 实现弱一致性同步,核心思路是“写隔离 + 乐观更新”,而非强一致互斥。
- 限速(limit_req):每个 worker 维护本地滑动窗口计数器;请求先查本地桶,额度不足时才用原子操作尝试扣减共享 zone 配额;失败即拒绝,视作临时过载
-
Lua 字典(lua_shared_dict):支持
incr、set(key, val, exptime)等原子方法;适合日粒度计数、用户频次控制;注意单次请求中多次incr可能导致精度漂移 - SSL 会话复用:session ID 直接写入共享哈希表槽位;所有 worker 共址访问,命中即复用;Linux/macOS 用 POSIX shm,Windows 因缺失支持退化为 per-worker builtin 模式
跨节点同步:NGINX Plus 的 zone_sync
单机内 zone 解决了多 worker 协同,但集群多节点间仍需数据同步。NGINX Plus 提供 ngx_stream_zone_sync_module,在节点间建立 TCP/SSL 连接,双向推送 zone 数据。
- 支持
limit_conn、HTTP sticky session、KV 类型 zone - 通过
zone_sync_server声明对端地址,zone_sync_interval控制同步频率(默认 1s) - 启用 TLS 加密需配置
zone_sync_ssl on及对应证书链,保障传输安全











