⭐ 推荐:社区规则条款 V1.0

列表页缓存与版本戳:发帖后立即生效的缓存设计

CLARA轻量论坛系统
CLARA轻量论坛系统 星耀SVIP星耀SVIP管理员管理员 黑卡会员黑卡会员
发布于 2026-08-19 08:38 ·75 浏览 ·0 回复
内容摘要

列表页缓存通过给缓存键附加作用域版本号,发帖等操作只自增版本号使旧键整体失效,版本号需持久化原子自增并配合TTL回收,从而避免主动删除大量缓存,实现发帖后立即可见。

列表页缓存想做到"发帖后立刻可见",正解不是发帖后去挨个删缓存,而是给缓存键挂一个版本戳:发帖、回帖、置顶、删帖时只把对应作用域的版本号 +1,新请求自然算出一个全新的键,旧缓存没人再读、到点自动回收。删缓存是 O(n) 的扫荡,改版本戳是一次 O(1) 的自增。

为什么"发帖后删缓存"这条路走不通

结论:列表页缓存从来不是"一份缓存",而是一大片,靠主动删除永远删不干净。

一个帖子发出去,会同时影响首页列表、所属版块列表、版块内子分类筛选页、按分类排序页、每一页分页——十几二十个键起步。你既不可能精确枚举出该删哪些键,也不可能保证不漏。

再往下想更麻烦:删漏一个,用户看到"我刚发的帖子不见了";删多了,等于每次发帖都把整站列表缓存清零,缓存命中率直接崩盘。加上多键遍历本身有开销,还容易误删到别的模块的键,这条路在工程上基本是负收益。

版本戳具体怎么设计

结论:缓存键 = 作用域 + 版本号 + 参数,事件发生时只动版本号。

设计三句话就能说清:

  1. 一个作用域一个版本号。全局列表一个(globalVer),每个版块一个(boardVer)。
  2. 键的拼法固定:list:v{globalVer}:home:p1、list:b{boardId}:v{boardVer}:cat3:p2,分页、排序、分类筛选全部进键。
  3. 触发点只管自增:发帖/回帖/置顶/加精/关闭/删除 → 递增对应版本号,自增是 O(1) 的整数操作。

新帖发布 → 版块版本号 7 变 8 → 原来 ...:v7:... 的所有键瞬间全部失效,请求直接算 v8。

版本号该存在哪里

结论:版本号不能只放缓存里,必须有一个持久、可原子自增的落脚点。

优先级从高到低:

  • 数据库一行(最稳):一张 cache_versions 表,scope 做唯一键,UPDATE ... SET ver = ver + 1。事务内自增,重启不丢,多进程并发也安全。
  • 文件:flock 写一个纯数字,够用但要处理权限和并发写。
  • 只放缓存:最危险。缓存一被清,版本号回退,旧键"复活",用户会读到过期列表。所以版本号必须有比缓存更持久的底座。

读取侧可以再加一层进程内缓存(比如同一请求周期内只查一次库),避免每个分页请求都去打数据库。

和 Clara BBS 这类轻量论坛的契合点

结论:版本戳的设计哲学和 Clara BBS「保存即生效、无需清缓存」的路子是一脉相承的。

Clara BBS 是无框架轻量级 PHP 论坛(PHP 7.4-8.5 + MySQL 5.7+,不需要 Composer、不需要命令行、没有编译缓存),后台改配置保存即生效,插件放进 content/plugins 也是保存即生效、无需编译——本质都是"不要让用户去手工清理,让旧状态自然失效"。

如果你要给这类系统的列表页加缓存,可以直接复用它的公共设施:Cache::remember 提供缓存能力,Cron::register 可以跑懒触发的清理任务。手工清理仍然保留了一个出口,在后台「系统工具 → 缓存清理」。另外像 GEO 问答工厂插件那样"发布问答后自动清缓存进问答池",就是按需失效的典型场景。

这几个坑一定要避开

结论:版本戳写错的地方,九成出在键的设计和 TTL 上。

  • 别用时间戳当版本号:同一秒内两个发帖会撞号,缓存不失效。用自增整数。
  • TTL 必须设:版本戳只负责"逻辑失效",旧键的物理空间还得靠 TTL 回收,建议 5–15 分钟,千万别设永久。
  • 分页、排序、筛选参数必须进键:少一个参数,翻到第 3 页给你第 1 页的内容。
  • 用户私有状态别进公共列表缓存:像"我是否已购买此帖""我是否点过赞"这类,要么单独走一份个人缓存,要么在渲染时独立取,否则会把 A 的状态穿给 B。
  • 并发递增是安全的:两个请求同时发帖,版本号 +2 无非多失效一次,不会读到脏数据。

一句话收尾:列表页缓存的正确姿势是"键里带版本、事件里加一、TTL 兜底",缓存只负责加速,版本戳负责正确性——两者分开,发帖后立即生效就是自然结果,而不是靠人去清。

本文转载自 Clara轻量论坛系统,原文地址:https://www.leleweb.cn/thread-498.html
转载请注明出处,版权归原作者所有。

全部回复 0

还没有回复,来抢沙发~