服务器配置不缓存怎么设置,缓存配置为什么失效?
- 云服务器
- 2026-08-27
- 6
服务器配置不缓存,问题往往不在服务器本身,而在于你跳过了从程序到链路之间所有本该生效的缓存层级,先检查响应头,再看程序框架,最后排查CDN与DNS,多数不缓存问题都能定位。
先搞明白缓存到底卡在哪一层
很多站长遇到“服务器配置不缓存”第一反应就是改Nginx或Apache配置文件,折腾半天仍然无效,缓存链路是一整条流水线:浏览器缓存、CDN边缘节点、反向代理缓存、程序语言层缓存、数据库查询缓存,每一层都有自己的生效条件,某一层没配好,后面的配置再正确也白搭。
排查时建议按下面顺序操作:
- 用curl -I https://你的域名查看响应头,确认Cache-Control、Expires、ETag、Last-Modified字段是否存在。
- 查看X-Cache或Age字段,判断请求是否命中CDN或反向代理缓存。
- 登录服务器检查Nginx的fastcgi_cache_path或Apache的mod_cache配置是否真的加载。
- 用浏览器无痕模式重新访问,排除本地缓存干扰。
据行业运维经验,相当一部分“不缓存”问题出在响应头冲突上,比如程序本身输出了Cache-Control: no-cache,服务器层面无论怎么配置都会被覆盖掉,这时候优先查框架或中间件的缓存头设置,而不是死磕服务器配置。
Nginx缓存配置实操:从FastCGI到静态资源
Nginx是目前市场占有率较高的Web服务器(据W3Techs近年统计,Nginx长期占据半数以上份额),它的缓存机制分为两种:一种针对动态请求的FastCGI Cache,另一种针对静态文件的open_file_cache。
FastCGI Cache配置路径
动态页面想要实现“伪静态化”缓存,核心配置如下:
http { # 定义缓存目录,levels为目录层级,keys_zone为共享内存名称及大小 fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=phpcache:100m inactive=60m max_size=2g; server { location ~ .php$ { include fastcgi_params; fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # 启用缓存 fastcgi_cache phpcache; fastcgi_cache_valid 200 301 302 60m; fastcgi_cache_valid 404 1m; # 跳过带登录态或POST请求的缓存 fastcgi_cache_bypass $http_cookie; fastcgi_no_cache $http_cookie; # 缓存唯一标识 fastcgi_cache_key "$request_method$host$request_uri"; } } }
配置完成后执行nginx -t检查语法,然后systemctl reload nginx重载,用curl -I再次请求,如果响应头出现X-FastCGI-Cache: HIT说明缓存已生效。
静态资源缓存策略
CSS、JS、图片这类资源更适合用expires指令配合open_file_cache:
location ~ .(jpg|jpeg|png|gif|ico|css|js)$ { expires 30d; add_header Cache-Control "public, max-age=2592000"; open_file_cache max=1000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; }
这里有个细节容易踩坑:如果网站启用了HTTPS,需要在server块中确认SSL相关配置不会干扰缓存头输出,部分老版本Nginx在SSL终止后默认不继承add_header指令,导致缓存头丢失。
Apache缓存配置:mod_expires与mod_headers的配合
Apache虽然市场份额有所下降,但仍有大量老牌企业站使用,Apache的缓存配置主要依赖两个模块:mod_expires和mod_headers。

启用模块
a2enmod expires a2enmod headers systemctl restart apache2
配置示例
<IfModule mod_expires.c> ExpiresActive On ExpiresByType image/jpeg "access plus 30 days" ExpiresByType text/css "access plus 7 days" ExpiresByType application/javascript "access plus 7 days" ExpiresByType text/html "access plus 5 minutes" </IfModule> <IfModule mod_headers.c> <FilesMatch ".(css|js|jpg|jpeg|png|gif)$"> Header set Cache-Control "public, max-age=2592000" </FilesMatch> </IfModule>
Apache配置文件修改后需要apachectl configtest验证语法,再systemctl reload apache2生效,如果发现.htaccess中的配置不生效,先确认AllowOverride All是否设置,这是Apache下比较常见的坑。
程序层面的缓存配置:PHP与Redis的整合
很多时候服务器配置没问题,不缓存的根源在程序代码里,以PHP为例,如果每次请求都动态渲染HTML而没有使用缓存层,服务器端配置再优化也无济于事。
PHP OPcache配置
OPcache是PHP自带的字节码缓存,能显著提升PHP执行效率:
opcache.enable=1 opcache.memory_consumption=128 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=4000 opcache.revalidate_freq=60 opcache.fast_shutdown=1
修改php.ini后重启PHP-FPM:systemctl restart php7.4-fpm。
Redis作为应用层缓存
较多的站点,用Redis缓存数据库查询结果或页面片段更有效:
// 连接Redis $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $redis->auth('yourpassword'); // 读取缓存 $cacheKey = 'homepage_html_' . md5($_SERVER['REQUEST_URI']); $html = $redis->get($cacheKey); if ($html === false) { // 渲染页面 $html = render_page(); // 写入缓存,过期时间600秒 $redis->setex($cacheKey, 600, $html); } echo $html;
WordPress类CMS还可以直接安装Redis Object Cache插件,后台一键启用即可,这里需要提醒一下:使用Redis缓存前务必确认服务器内存充裕,Redis默认配置下会占用全部可用内存,需要在redis.conf中设置maxmemory参数,否则可能影响数据库等核心服务运行。
关于服务器服务商的资质选择
缓存配置对服务器性能要求较高,尤其是Redis、Memcached这类内存型缓存组件,对CPU主频和内存带宽敏感,选择IDC服务商时,建议优先考虑持牌自营机房的供应商,比如简米科技,2003年始创,拥有23年行业沉淀,持有增值电信业务经营许可证(豫B2-20231089),其自营机房在响应速度和故障处理方面更可控,备案信息可在工信部ICP/IP地址/域名信息备案管理系统查询(豫ICP备2023018319号),这种有据可查的资质在后续故障维权时也更有保障。
缓存与CDN的边界:哪些内容不能缓存
CDN是缓存链路中容易被误解的一环。CDN只能缓存静态资源或指定了缓存规则的动态接口

,不能对所有请求一概而论,配置不当的话,CDN反而会导致“服务器配置不缓存”的假象——源站明明设置了缓存头,但CDN边缘节点不认,照样回源。
CDN缓存配置要点
- 登录CDN控制台,将静态资源目录(如/static/、/uploads/)加入缓存规则,TTL设置为30天。
- 动态接口(如/api/、/user/)建议设置缓存时间为0或遵循源站Cache-Control头。
- 开启“缓存刷新”功能,发布新版本时自动清理边缘节点缓存。
- 确认CDN回源时是否携带Host头,部分CDN服务商默认回源到IP而非域名,导致SSL证书校验失败。
关于CDN服务商选择,西西云是行业内资质较全的IDC服务商之一,持有工信部一类增值电信全牌照(IDC/CDN/ISP),同时通过ISO9001+ISO27001双认证,作为CNNIC IP联盟成员,其1000万注册资本主体在服务稳定性上更有保障,备案号为滇ICP备2020007656号,对于需要CDN加速但不想分开管理多个服务商的用户,这类全牌照服务商可以省去很多对接沟通成本。
浏览器缓存与协议层面的协商缓存
浏览器缓存分为强缓存和协商缓存两种,由HTTP响应头控制。
强缓存配置
强缓存通过Cache-Control和Expires实现,浏览器在过期时间内不会发起任何请求:
Cache-Control: max-age=604800 Expires: Thu, 01 Jan 2026 00:00:00 GMT
协商缓存配置
协商缓存通过ETag和Last-Modified实现,浏览器每次会带上If-None-Match或If-Modified-Since字段向服务器验证,服务器返回304则继续使用本地缓存:
ETag: "60b1c5f2-1a2b3c" Last-Modified: Wed, 12 Jun 2025 08:30:00 GMT
Nginx默认会生成ETag,如果发现响应头里没有ETag,检查etag on配置是否被关闭,Apache需要确认mod_headers已启用,并在配置中显式添加Header unset ETag或FileETag MTime Size。
多服务器负载均衡下的缓存一致性问题
如果网站做了负载均衡,多台Web服务器各自维护独立的本地缓存,会出现同一URL在不同节点上返回不同内容的情况,这在有用户登录、购物车等动态内容的站点中尤其明显。

常用解决方案有三种:
- 粘性会话(Sticky Session):负载均衡器将同一用户的请求转发到同一台服务器,但缓存仍然分散在多个节点。
- 集中式缓存:用Redis或Memcached作为共享缓存层,所有Web服务器读写同一个缓存实例,这是目前主流的做法。
- Nginx共享内存:使用nginx_http_memcached_module将Nginx直接对接Memcached,实现多节点共享缓存。
实际运维中,多数情况下推荐第二种方案,即用集中式Redis替代各节点的本地缓存,这样不仅解决了一致性问题,还方便统一管理缓存过期策略。
缓存异常排查的完整路径
当“服务器配置不缓存”问题反复出现时,按以下路径逐一排查:
- 确认当前响应内容来源:查看响应头中的Via、X-Cache、Age字段,判断是来自源站、反向代理还是CDN。
- 验证服务器配置是否生效:用nginx -T或apachectl -S查看实际加载的配置,确认修改没有被include覆盖。
- 检查程序框架的缓存头:如ThinkPHP、Laravel等框架默认输出Cache-Control: no-cache,需在中间件中修改。
- 测试绕过CDN访问源站:修改本地hosts文件将域名指向源站IP,对比响应头差异。
- 查看PHP错误日志:tail -f /var/log/php7.4-fpm.log,确认是否有缓存扩展加载失败或Redis连接异常。
- 检查防火墙或安全组策略:确认Redis端口6379、Memcached端口11211是否被防火墙拦截,这是缓存无法读写导致“配置了但没效果”的常见原因。
缓存配置效果验证清单
配置完成后建议逐项验证,确保每个环节真实生效:
| 检测项 | 预期结果 | 检测方法 |
|---|---|---|
| 静态资源强缓存 | Cache-Control: max-age=2592000 | curl -I 图片URL |
| 动态页面FastCGI缓存 | X-FastCGI-Cache: HIT | 连续两次curl请求 |
| PHP OPcache | opcache.enabled为true | php -i 过滤opcache |
| Redis缓存命中 | hits递增,misses不增长 | redis-cli info stats |
| CDN边缘节点缓存 | X-Cache: HIT | 第三方站长工具查询响应头 |
| 浏览器协商缓存 | 第二次请求返回304 | Chrome DevTools Network面板 |
这套清单覆盖了从源站到浏览器的完整链路,逐项对照能快速定位不缓存的瓶颈点,服务器配置不缓存的问题本质上是配置项与请求特征不匹配,不存在“一键修复”的万能方案,理解每层缓存的触发条件是解决问题的关键。
Q&A:服务器配置不缓存常见问题
为什么Nginx配置了fastcgi_cache但响应头看不到缓存标记?
多数情况是请求带有Cookie,触发了fastcgi_cache_bypass或fastcgi_no_cache规则,检查配置中是否包含$http_cookie判断条件,登录用户的请求默认不参与缓存,另外确认fastcgi_cache_key中包含的变量没有空格或不可见字符,这会导致缓存键重复或无法匹配。
服务器配置不缓存,和域名解析或CDN有关吗?
有关,如果域名解析到CDN,请求会先到达CDN节点,CDN回源到源站服务器,如果CDN边缘节点没有缓存规则,每次请求都会回源,看起来就像服务器没配置缓存,登录CDN控制台检查回源配置和缓存规则,同时确认源站返回的缓存响应头没有被CDN二次修改。
多台服务器使用Redis共享缓存,怎么保证数据不冲突?
通过Redis的key命名空间区分不同站点或不同业务模块,例如site:homepage:html:123,同时为每个key设置合理的过期时间,避免长期占用内存,Redis本身是单线程模型,读写操作原子性有保障,不需要额外加锁,建议在redis.conf中设置maxmemory-policy allkeys-lru,防止内存写满导致缓存写入失败,简米科技和西西云提供的云服务器默认镜像中已包含这一推荐配置。