3.3 写入、TTL与失效:平台缓存的生命周期 本节摘要:平台缓存不是永久资产,而是一条有寿命的条目。它从"未缓存"经首次请求写入,在多次命中间被复用,因 TTL 超时或前缀变动而被逐出,下次命中再重写。理解这条状态链,才知道省下来的折扣为什么需要被"维护",以及发布新版本前为什么要先预热。 从写入到逐出:缓存条目的寿命 3.2 节的公式把命中率当成一个给定数字,好像它永远稳定。现实里命中率会跳——因为缓存条目自己有生命周期。一笔前缀第一次被请求时,平台现算并写入缓存;之后相同前缀的请求命中它、复用它;一旦闲置超过 TTL,平台把它逐出;你再请求时又得重写。这条链画出来是一个状态机。 状态机里有五个值得记住的点。第一,"未缓存"到"写入"发生在首次请求,这一跳要付写价,就是 3.
本节摘要:平台缓存不是永久资产,而是一条有寿命的条目。它从"未缓存"经首次请求写入,在多次命中间被复用,因 TTL 超时或前缀变动而被逐出,下次命中再重写。理解这条状态链,才知道省下来的折扣为什么需要被"维护",以及发布新版本前为什么要先预热。
3.2 节的公式把命中率当成一个给定数字,好像它永远稳定。现实里命中率会跳——因为缓存条目自己有生命周期。一笔前缀第一次被请求时,平台现算并写入缓存;之后相同前缀的请求命中它、复用它;一旦闲置超过 TTL,平台把它逐出;你再请求时又得重写。这条链画出来是一个状态机。
状态机里有五个值得记住的点。第一,"未缓存"到"写入"发生在首次请求,这一跳要付写价,就是 3.2 节说的溢价。第二,"命中"是自循环——只要前缀不变且没超时,每次都走这条便宜的路。第三,"过期"不需要任何错误,纯粹是平台嫌你太久不来,把稀缺的缓存位让给更热的请求。第四,"重写"和"写入"代价一样,都是全价加写价。第五,"失效"和"过期"不同:过期是时间问题,失效是内容问题——你改了前缀或换了模型,老条目彻底作废。
TTL(存活时间)是这条链里最影响命中率的旋钮,四家却各有一套脾气。
工程含义很直接:如果你的流量是"白天高峰、夜里归零",夜间冷启动那一波请求几乎必然重写,有效单价会在每天开机时回弹到接近 1.0。把这一点算进 3.2 的月度账,别假设命中率全天恒定。
要搞清"什么会破坏命中",得先知道缓存键长什么样。四家底层都是前缀精确匹配,但"前缀"的范围不止你看到的文字:
这句话的潜台词是:缓存键不是"你的 System Prompt 文本",而是"从开头到断点的整段请求上下文 + 模型标识"。凡是出现在这段里、又经常变的东西,都是命中率的杀手。
把缓存键的构成反过来看,失效只有三种根源:
三种里,第二种最该被工程师盯紧,因为它往往是无意的。3.4 节会专门讲怎么把"易变内容"从前缀里请出去。
知道了缓存会被逐出、会被失效,生产环境就有了一个标准动作——预热。当你要发布一版新的 System Prompt、新的工具定义,上线瞬间所有老缓存失效,第一波真实用户请求会集体触发重写,付写价不说,还会因为集中重算造成延迟尖峰。
预热的做法很简单:正式放流量前,用这份新前缀先打一轮请求把缓存填好。可以是一组覆盖典型问题的探测请求,也可以是直接复刻一份线上样例流量。填完之后,真实流量一来就已经命中,延迟平稳、账单也从第一笔就走读价。这个动作在 3.5 节的长文档场景尤其关键——一份几万 token 的文档前缀,冷启动重写一次的成本很可观,预热一次能避免整批用户的卡顿。
用一组构造数字把"TTL 折旧"算实。假设某业务固定前缀 8000 token,白天每 30 秒一个请求,夜间 8 小时仅零星请求。白天时段:请求间隔远小于 TTL,缓存条目始终存活,命中率稳定在 95% 以上,有效单价贴近读价。夜间时段:请求间隔动辄数十分钟,超过多数平台的短保留窗口,每一笔都是"过期→重写",全额付写价。把两段流量按 70:30 加权,整体有效单价比"全天恒定 95% 命中"的假设高出约四成——这个差距全部来自夜间折旧,而它完全可以被预判。
对策落在排班上:夜间批处理任务(对账、报表、巡检)如果能共享同一份前缀,恰好充当了"保活流量",让白天业务的开机成本归零。这也是为什么很多团队把定时任务的前缀刻意设计成与线上服务一致——缓存维护被顺手做掉了。
把生命周期放回 3.2 的公式:有效单价公式里的命中率 r,不是常数,而是"流量连续性"和"前缀稳定性"的函数。TTL 短的平台,r 随夜间闲时掉;前缀常变的业务,r 随每次发版掉;换模型的发布日,r 直接归零再爬回。所以评估缓存值不值,不能只看稳态命中率,要看"命中率的最低谷"——那个谷决定了你最贵的一笔请求付多少。
关键直觉:缓存是资产,但资产会折旧。TTL 是折旧时钟,前缀变动是损毁事件。预热,就是上线前给资产做一次充值。