nginx通过master-worker多进程模型配合共享内存与ngx_shmtx_t自旋锁实现跨进程协同:master创建共享内存区供worker继承,自旋锁基于原子操作实现无系统调用的高效同步,并按哈希分桶、slot分片及cache line对齐优化锁粒度,accept_mutex则缓解惊群问题。

Nginx 多进程架构不依赖线程,而是靠 master-worker 模型运行多个独立 worker 进程。这些进程间不能直接共享变量,但像限流计数、连接限制、SSL 会话缓存等关键状态必须跨进程协同——这就需要共享内存 + 精细的互斥机制。
共享内存是基础载体
所有需要跨进程访问的数据(如 limit_req_zone、limit_conn_zone、ssl_session_cache)都通过 keys_zone 参数定义共享内存区,例如:
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
master 进程在启动时创建该内存段(用 shm_open 或 mmap),并映射到自身地址空间;fork 出的每个 worker 进程自动继承该映射,所有进程操作的是同一块物理内存页上的结构体。
ngx_shmtx_t 自旋锁是核心同步手段
Nginx 不用系统级互斥锁(如 pthread_mutex),而是基于原子操作实现轻量级自旋锁 ngx_shmtx_t:
- 锁本质是一个 32 位原子整型(
ngx_atomic_t),通常位于共享内存头部 - 获取锁时循环执行原子比较交换(
CMPXCHG):若值为 0(空闲),则设为 1 并成功进入临界区 - 失败后调用
PAUSE指令短暂等待,避免总线争抢;默认最多自旋 1024 次,超时后调用sched_yield()让出 CPU - 释放锁即原子写回 0,无系统调用开销
锁粒度按需分片,避免全局竞争
为减少冲突,Nginx 不对整个共享内存区用一把大锁:
-
limit_req_zone按客户端哈希值分桶,每个 bucket 独立配一把锁 - SSL 会话缓存将 session key 哈希后映射到固定 slot,slot 内部再加锁保护链表操作
- 结构体内插入 padding,确保锁变量与热点数据各自独占 CPU cache line(64 字节),防止伪共享
accept_mutex 解决监听套接字惊群问题
worker 进程争抢新连接时,若全部同时唤醒会导致内核调度压力过大:
- 启用
accept_mutex on后,仅一个 worker 能持有锁并调用accept() - 内核 ≥ 4.5 且启用
EPOLLEXCLUSIVE时,可关闭该锁(accept_mutex off),由内核保证单 worker 唤醒 - 锁竞争失败后等待时间由
accept_mutex_delay控制,默认 500ms,微调可平衡延迟与 CPU 占用











