nginx通过shared:前缀在http块声明共享内存区(如shared:sslcache:10m),由master进程创建posix共享内存,所有worker映射共址访问;内置分桶自旋锁(每bucket独立ngx_shmtx_t)保障并发安全,无全局锁、无同步广播,避免写冲突。

直接在 Nginx 配置中定义带锁保护的共享内存区,就能解决多 worker 进程对 SSL 会话缓存的并发写冲突。关键不是“手动加锁”,而是让 Nginx 自动用分桶自旋锁管理内存块。
用 ssl_session_cache 指令声明共享内存区
在 http 块中配置:
- 指定名称和大小,例如
ssl_session_cache shared:sslcache:10m - 名称(如
sslcache)会被 master 进程用于创建 POSIX 共享内存段 - 大小(如
10m)决定能缓存的会话数量,一般每条会话占约 256 字节,10MB 约支持 4 万个会话 - 不加
shared:前缀(比如只写ssl_session_cache builtin:1000)会导致每个 worker 使用独立内存,无法协同,不能解决跨进程冲突
理解背后的锁机制如何避免统计竞争
Nginx 不会对整块内存加一把大锁。它把共享内存按哈希划分为多个 bucket,每个 bucket 内部配一把独立的 ngx_shmtx_t 自旋锁:
- 会话 key(如 session ID 的 SHA-1 哈希)决定落在哪个 bucket
- worker 进程查找或插入会话时,只争抢对应 bucket 的锁,而非全局锁
- 锁操作基于 CPU 原子指令(如
CMPXCHG),无系统调用,开销极低 - 若自旋超 1024 次未获取成功,自动让出 CPU,防止饿死
配合其他指令提升缓存有效性
单靠分配内存不够,还需控制生命周期与复用逻辑:
- 用
ssl_session_timeout 4h设置会话有效期,避免过期数据长期占位 - 开启
ssl_buffer_size 4k可减少 TLS 握手包分片,间接降低会话新建频率 - 若启用了 OCSP stapling,确保
ssl_stapling on与缓存区共用同一 zone(Nginx 1.19+ 支持),避免额外锁竞争
验证是否生效的简单方法
无需写代码,通过 Nginx 自带指标观察:
- 访问
/nginx_status(需启用stub_status)查看 active connections 和 SSL handshakes/sec - 检查 error log 中是否出现
could not allocate new session—— 出现说明内存不足或锁争抢严重,需增大 zone 或调优 timeout - 用
ipcs -m查看系统级共享内存段,确认名称为/nginx_sslcache(Nginx 内部会将 zone 名转为 POSIX 名)且权限为rw-------











