跳转到主要内容
杨月昌的软件博客
返回

提升 Web 性能:基于 Nginx 和 Memcached 的页面缓存方案

1. 为什么选择 Nginx + Memcached?

在传统的 Web 架构中,即使使用了后端缓存(如在 PHP 或 Python 代码中调用 Redis),请求依然需要经过 Nginx -> 后端应用解析器 -> 缓存系统 这一漫长的链路。

通过使用 Nginx 的 ngx_http_memcached_module 模块,我们可以实现 Nginx -> Memcached 的直接通信。当缓存命中时,请求无需触达后端应用逻辑,从而实现“零开销”分发动态内容,单机并发处理能力通常可提升数倍甚至数十倍。


2. 工作原理图解

  1. 请求拦截:Nginx 接收请求,根据预设规则生成缓存键(通常基于 URL)。
  2. 直接提取:Nginx 发起向 Memcached 的异步查询。
  3. 缓存命中 (Hit):数据直接由 Nginx 返回客户端,耗时极低。
  4. 缓存未命中 (Miss):Nginx 通过 error_pagetry_files 将请求回源给后端应用(如 FastCGI),后端处理完逻辑后将结果回写至 Memcached。

3. 生产环境配置指南

第一步:配置 Nginx 缓存逻辑

在 Nginx 配置文件中,我们需要定义上游服务器地址,并精细化处理请求头,以确保缓存能够正确返回。

# 定义 Memcached 集群
upstream memcached_backend {
    server 10.1.240.166:11211;
    keepalive 32; # 保持长连接,提升性能
}

server {
    listen 80;
    server_name example.com;

    location / {
        # 1. 定义缓存 Key:这里使用完整请求 URI
        set $memcached_key "$request_uri";
        
        # 2. 尝试从缓存中获取
        memcached_pass  memcached_backend;
        
        # 3. 设置默认类型及响应头以便调试
        default_type    text/html;
        add_header      X-Cache-Status HIT;
        add_header      X-Memcached-Key $memcached_key;

        # 4. 如果发生错误(404/502/504),则跳转到内部命名的 location @fallback
        error_page      404 502 504 = @fallback;
    }

    # 后端逻辑处理与缓存写入
    location @fallback {
        add_header      X-Cache-Status MISS;
        proxy_pass      http://your_backend_server; # 或者 fastcgi_pass
    }
}

第二步:后端应用写入缓存(以 PHP 为例)

后端不仅要负责处理业务逻辑,还要在生成内容后,将结果通过 Key-Value 形式存入 Memcached。

<?php
$m = new Memcached();
$m->addServer('10.1.240.166', 11211);

// 建议使用当前请求的 URI 作为 Key
$cacheKey = $_SERVER['REQUEST_URI'];
$content = $m->get($cacheKey);

if ($content) {
    echo $content;
} else {
    // 开启缓冲区捕获页面输出
    ob_start();
    
    // 执行复杂的业务逻辑、数据库查询等
    render_complex_page();
    
    $output = ob_get_contents();
    ob_end_flush();

    // 存入缓存,设置过期时间(例如 3600 秒)
    $m->set($cacheKey, $output, 3600);
}

4. 关键避坑与进阶建议

4.1 内容类型(Content-Type)丢失问题

标准的 ngx_http_memcached_module 并不存储 HTTP 头信息。如果你的页面有多种 MIME 类型,直接读取可能会导致浏览器无法正确识别 HTML 或图片。

4.2 缓存压缩(Gzip)

为了节省内存,后端通常会将内容压缩后存入 Memcached。

4.3 缓存失效(Cache Invalidation)

Memcached 不支持模糊删除。如果某个新闻分类下的所有页面都变了,你很难一次性清除所有相关的 Key。


5. 方案对比:Memcached vs Redis

特性MemcachedRedis
性能极高(简单 KV 协议,系统开销更小)高(功能丰富,略有系统开销)
持久化不支持支持
Nginx 支持原生模块支持,配置简单需安装 srcache-nginx-module 等第三方模块
数据类型仅字符串字符串、哈希、列表、集合等

6. 总结

结合 Nginx 与 Memcached 的页面缓存方案是 “用空间换时间” 的经典实践。它尤其适用于:

  1. 高频访问的 CMS 页面(如新闻首页、公告)。
  2. API 查询结果缓存
  3. 计算代价昂贵的报表页面

虽然现在 Redis 非常流行,但在追求极致的简单 KV 查询性能时,Nginx + Memcached 的原生组合依然是运维利器。



上一篇
在 MedusaJS 与 Next.js 店面中实现产品评论功能的完整教程
下一篇
彻底解决 CDN/反代后 Nginx 获取不到真实 IP 的实战指南