base_blog 缓存体系升级:sofutCache(LMDB) + CacheFlash 统筹刷新

这个 blog 从 2024 年起停止更新,2026 年重启的第一件事,就是把缓存体系彻底升级。本文记录这次升级的两个核心:底层换上 sofutCache(LMDB)缓存引擎,上层新建 CacheFlash 缓存统筹刷新类。
一、底层引擎:从 SQLite 到 LMDB
框架原来的缓存驱动是单个 SQLite 文件,读写都要走 PDO + SQL。现在换成了自研的 PHP 扩展 sofutcache(Rust 引擎 + LMDB 0.9.33),同样的接口,完全不同的性能:
| 场景 | sofutCache | SQLite(同耐久性) | 倍数 |
|---|---|---|---|
| 缓存命中(每请求 open+读+close) | 0.43~0.47ms | 1.09~1.43ms | 2.4~3.2x |
| 冷启动 | 1.61~1.93ms | 5.69~6.75ms | 3.5~4.0x |
| 命中·常驻句柄(不含 open) | 0.01ms | 0.84~1.26ms | 84~126x |
差距几乎全在"读"上。扩展的 keep_env=1 让 LMDB 环境在 php-cgi 进程里常驻(一个进程要处理上万个请求),页缓存与文件锁都不丢。数据目录放在点目录 cache/.storage/lmdb 下,整目录对 Web 不可访问。
二、缓存形态:一切都是"数组缓存"
这个站的缓存很简单:每个键对应一个数组(serialize 存储)。首页、文章页、分类页、归档页、侧栏,各有一组固定命名的键:
- 首页:
home_main_info - 文章页:
home_post_info_{id}_{page} - 分类页:
home_cate_info_{linkname}_{page}、home/category/{linkname}/{page}.html>>list - 归档页:
home_date_info_{year}_{month}_{page} - 侧栏(left):
home/side/new|newscat|tags|archiver|hot|recom/list共 6 条 - 站点:
site_rss_info、site_sitemap_info
三、痛点:发一篇文章,牵连十几条缓存
发一篇文章,首页列表、侧栏"最新文章"、所在分类页、当月归档、RSS……全部过期。老办法是全库删除重建——几千上万条缓存键,删掉再一条条重建,代价不可接受。
正确做法是精确刷新:只动受影响的那十几条。于是有了 CacheFlash。
四、CacheFlash 1.1:删除 + 重算写回,一步做完
tcore\CacheFlash 是缓存键名的唯一权威来源(对照表写在文件头注释),提供两种模式:
- del 模式:精确 DELETE 受影响键,前台访客首次访问时自动重算写回(懒重算,零风险兜底)。
- update 模式:后台直接重算数组并
iSet_day写回——重算复用 btnCore 数据层(iHomeMainInfo / iHomeCateInfo / iHomeDateInfo / iHomePostInfo),和前台访客触发重算跑的是同一套代码,所以写回的数据与前台永远一致。发完文章那一刻,缓存已经是新的。
任何一组重算失败(如文章不存在),自动退回失效 + 懒重算,绝不阻塞发文。侧栏最省事:先失效 6 个键,再跑 iHomeMakeSide——它原生逻辑就是"键不存在就重算并写入",等价于强制重建。
量化一下:发一篇文章刷新 23 条缓存键,对比老办法的全库重建 10000 条——工作量 23 : 10000。
五、后台体验
- 发文即刷:后台发文/改文成功后,
adbWestNewsAdd的 reset 阶段自动调CacheFlash::flashNews(),返回每组刷新报告(update/del)。 - 缓存列表:后台「工具 → 缓存列表」按
dlog_cache_work登记逐条刷新,flashFromWork()一口气消费全部待办并置 isok=1。
结语
从"删一万条重建"到"精确刷 23 条 + 主动写回",这次升级让停更两年的 blog 重新具备了高频更新的底气。1.0 用一个下午落地,1.1 的主动重算当天完成——先做出来,再优化,永远是对的。
评论列表:0