nginx缓存命中率需按六种状态(hit/miss/expired/bypass/stale/revalidated)分类统计,避免混计失真;须确保$upstream_cache_status正确采集、日志格式结构化、按业务路径分离日志,并依目标选择分母口径。

要分析 Nginx 缓存命中率,核心不是看“有没有缓存”,而是看日志里每个请求到底经历了哪种缓存行为——HIT、MISS、EXPIRED、BYPASS、STALE、REVALIDATED 这六种状态各自代表不同逻辑环节,混在一起统计会严重失真。
确保日志能真实记录缓存状态
如果日志中 $upstream_cache_status 字段大量为 - 或空值,说明变量没被有效采集。常见原因包括:
- 对应 location 块未配置
proxy_cache my_cache(必须引用已定义的 keys_zone) - 后端响应头含
Cache-Control: no-store、Set-Cookie或Vary: *,导致 Nginx 默认跳过缓存 - 误在静态文件 location 中使用
$upstream_cache_status(它只对 proxy_pass 有效;静态资源直出应改用$sent_http_x_cache等自定义头) - log_format 定义在 server 块内,但 access_log 写在 http 块,作用域不匹配
定义结构化日志格式
在 http 块中统一定义 log_format,显式包含关键变量:
log_format cache_log '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $upstream_cache_status $upstream_response_time $request_time';
再为不同业务路径单独切分日志,例如:
- 静态资源:用独立 location +
access_log /var/log/nginx/static.log cache_log - API 接口:用另一 location +
access_log /var/log/nginx/api.log cache_log
避免所有流量挤在同一个 access.log 里,干扰统计精度。
按业务目标选择统计口径
命中率不是固定公式,要根据优化目标选分母:
-
缓存机制整体利用率:分母 = 所有非
-的状态(HIT + MISS + EXPIRED + BYPASS + STALE + REVALIDATED) - 用户实际获得新鲜响应的比例:排除 BYPASS(根本没走缓存)和 STALE(返回过期内容),分母 = HIT + MISS + EXPIRED + REVALIDATED
- 回源压力评估:把 EXPIRED、MISS、BYPASS、REVALIDATED 都算作“需回源”,只将 HIT 和 STALE 视为“未触发新回源”
快速验证与基础统计
重启 Nginx 后,发起两次相同请求(首次应为 MISS,第二次应为 HIT),检查日志末尾是否出现类似 HIT 0.003 或 EXPIRED 0.217 的字段。
用 awk 快速估算最近 1 小时命中率(以 HIT / 总有效请求计):
awk '$12=="HIT" {hit++} $12 ~ /^(MISS|EXPIRED|BYPASS|STALE|REVALIDATED)$/ {total++} END{printf "%.1f%\n", hit/(hit+total)*100}' /var/log/nginx/api.log
注意字段序号需按你 log_format 中 $upstream_cache_status 的实际位置调整(通常为第10–12位)。











