帝国CMS站群缓存优化实战:从频繁回源到命中率翻倍
帝国CMS做站群,缓存没配好,服务器负载会高得离谱。我们手头这套站群从 12 个站点扩到 37 个之后,后台生成一篇文章,前台要等三四秒才出结果,CPU 直接顶到 90% 以上。折腾了一周多,把缓存链路重新理了一遍,现在单篇文章生成到前台可见稳定在 0.4 秒左右。

站群缓存到底卡在哪:先看清回源路径
很多人以为开了静态化就万事大吉。实际不是。帝国CMS 的静态化生成的是 .html 文件,但栏目页、列表页、内容页各自的生成规则不一样,站群模式下每个子站都挂着自己的模板目录,系统会按照站点 ID 分别去读模板和缓存文件,目录层级比单站深一层。
我们当时的问题出在数据表查询上。37 个站点共用一套主库,每次生成页面都要跑一次栏目关联查询,SQL 执行时间在 80ms 上下,量一上来就拖垮了。后来把 e/data 下的缓存文件单独做了目录映射,减少文件系统寻址开销,CPU 占用先降了一截。
静态化规则要按站点逐个调,不能一刀切
后台「系统设置-静态页面」里有个生成选项,站群模式下建议把栏目页和内容页分开配置。资讯量大的子站设成定时生成,比如每 30 分钟跑一次;更新频率低的子站直接手动生成,避免无意义的重复写入。
有个细节容易忽略:帝国CMS 的「刷新首页」和「刷新内容页」其实是两个独立队列。站群一多,队列会互相挤占。我们在 crontab 里把不同站点的生成任务错开 5 分钟执行,实测下来磁盘 IO 峰值下降了大概四成。
- 高频更新的子站:内容页按栏目生成,栏目页整点刷新
- 低频子站:关闭自动生成,改由编辑手动触发
- 生成时间错峰:每个站点间隔 5 分钟以上,避免同时写盘
内存缓存层怎么挂:eAccelerator 与文件缓存的取舍
纯文件缓存扛不住站群规模。我们在 PHP 7.4 环境上挂了 eAccelerator,把编译后的 opcode 缓存下来,页面首次执行时间从 200ms 降到 60ms 左右。注意版本要对齐,PHP 7.4 配 eAccelerator 0.9.6.1 比较稳,再高容易在并发写缓存时出段错误。
帝国CMS 自带的缓存机制偏向文件存储,开启 eAccelerator 后需要在 config.php 里确认缓存驱动没被覆盖。这点我没实测所有版本,只在 7.5 上跑通过,其他版本建议先在测试环境验证。
另外提一句,Redis 也能用,但帝国CMS 原生对 Redis 的支持不算深,站群场景下要自己写钩子做缓存键的站点隔离,维护成本偏高,小团队建议先走文件缓存加 opcode 缓存的组合。
数据表瘦身与索引:缓存命中率的隐形推手
缓存文件生成得再快,底下的查询慢一样白搭。我们给 phome_ecms_news 表加了 (classid, newstime) 复合索引,列表页查询从 120ms 压到 15ms 上下。站群模式下 classid 是跨站点区分的,索引顺序不能反。
还有 phome_enewsfile_1 这类附件表,站群跑久了体积膨胀得厉害,定期清理失效记录能明显减少缓存重建时的扫描量。这个操作建议放在凌晨低峰期,清理前先备份。
负载均衡下的缓存同步:一个绕不开的坑
站群上到多台 Web 节点之后,缓存文件不同步是家常便饭。A 节点刚生成的静态页,B 节点读不到,用户刷新几次看到的内容会跳变。我们的处理方式是用 rsync 在生成任务完成后触发一次增量同步,只同步 e/data 和 html 目录。
同步间隔设得太密会加重磁盘负担,太疏又影响一致性。目前定的是生成后 2 分钟内触发,接受短暂的缓存不一致。如果对实时性要求高,可以考虑共享存储挂载,但 IO 性能会打折扣,需要自己权衡。
最后提醒一点:帝国CMS 后台的「清理缓存」按钮不要随手点。站群模式下它会清掉所有子站的缓存文件,重新生成期间前台会频繁回源,负载瞬间冲高。建议改成按站点清理,或者干脆用脚本控制清理时机。