news 2026/1/30 12:10:16

艾体宝干货 | 三层缓存架构扛住流量冲击,源站稳如泰山

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
艾体宝干货 | 三层缓存架构扛住流量冲击,源站稳如泰山

在后端开发中,Redis 几乎就是缓存的代名词。用它撑业务规模的扩张确实信手拈来,但每逢大促、新品上线这类关键节点,总不乏意外发生:缓存命中率跳水,源站 CPU 飙升到 100%,值班群里的告警提示刷个不停。而这时再堆 Redis 节点往往是杯水车薪,真正的解法,是搭建一套「CDN + 边缘 KV + 源站缓存」的分层架构,配上灵活的 TTL 策略,让缓存命中成为常态,源站彻底告别击穿焦虑。

缓存的分工逻辑

缓存的核心是 “让数据离用户更近”,分层架构就是把这个逻辑做到极致。我把它总结为 “三环防御体系”,每一层都有明确的职责,且共用一套核心规则:

第一层:CDN 全球前置

作为用户请求的 “第一接触点”,CDN 最擅长处理**准静态内容**—— 比如带签名的图片、公开 API 响应、静态 HTML 片段,只要能通过 “URL + 请求头” 定位的内容,都该交给它。优势是地理节点密集,用户在哪都能快速取到数据,直接挡住 70% 以上的源站请求。

第二层:边缘 KV 承接动态热点

CDN 搞不定完全动态的内容(比如个性化推荐片段、实时聚合的 API 结果),但这些内容重新计算又特别费资源。这时边缘 KV 就派上用场了 —— 像 Cloudflare KV、Vercel Edge Store 这类服务,能在每个区域提供低延迟的键值存储,专门缓存 “热点动态数据”。比如电商商品详情页的库存模块、用户的个性化首页片段,用它存一波,响应速度能快上几十毫秒。

第三层:Redis/Memcached 兜底

这层是离源站最近的最后一道防线,存那些不适合放边缘但又天天被访问的东西,比如用户登录后的会话信息、数据库查出来的订单统计。

这三层要共用一套语言体系:​软 TTL、硬 TTL、失效重验证、击穿防护​,这样缓存逻辑就不会乱。

生产级 TTL 策略:如何既保速度又保准确

很多人用缓存只设一个过期时间,这是最大的误区。真正能抗住压力的缓存,靠的是分层过期逻辑:

核心概念

  • 硬 TTL​:绝对过期时间,过了这个点,数据再用就可能出问题,必须作废。比如商品价格缓存,硬 TTL 设 10 分钟,需要保证不会展示过期售价。
  • 软 TTL​:“新鲜度窗口”,过了这个时间,数据不算 “最新”,但还能用。比如商品详情页的描述信息,软 TTL 设 1 分钟,轻微延迟更新不影响用户体验。
  • ​**Stale-while-revalidate(SWR)**​:过了软 TTL 后,先给用户返回过期数据,同时偷偷去源站刷新缓存。用户感觉不到延迟,数据也能慢慢更。
  • Stale-if-error​:源站挂了的最后一层保障,这时只要没超过硬 TTL,就返回过期数据。

这些策略不是空谈,CDN 能通过 HTTP 头配置,Redis、边缘 KV 能通过代码实现,上手很简单。

实操指南:从配置到代码落地

CDN 层

CDN 的缓存逻辑靠 Cache-Control 头控制,我常用这套配置:

Cache-Control: public, max-age=60, stale-while-revalidate=600, stale-if-error=600 Vary: Authorization, Accept-Encoding Surrogate-Key: product:123 category:shoes

之前我们帮助客户优化首页 API 时,加了这几行头,源站请求量直接降了 80%,p95 延迟从 500ms 压到 150ms。

边缘 KV 层:动态内容的缓冲

以 Cloudflare Workers 为例,用边缘 KV 实现分层 TTL 其实很简单。核心逻辑是 先查缓存,新鲜就返回,软过期就兜底 + 刷新,硬过期再回源:

// edge-cache.ts (Cloudflare/Vercel 风格边缘运行时) type CacheEntry = { body: string; softExp: number; hardExp: number }; const SOFT_TTL = 60; // 秒 const HARD_TTL = 600; export default async function handler(req: Request) { const key = await cacheKey(req); // 例如:稳定的 URL + 用户细分 const now = Math.floor(Date.now() / 1000); // 1) 尝试边缘 KV const kvHit = await EDGE_KV.get<CacheEntry>(key, "json"); if (kvHit) { if (now <= kvHit.softExp) return ok(kvHit.body, true); // 新鲜数据 // 软过期:返回过期数据 + 在后台刷新 refreshLater(key, req); if (now <= kvHit.hardExp) return ok(kvHit.body, true); // 允许返回过期数据 } // 2) 回退到源站(带缓存击穿控制) const body = await singleFlight(key, () => fetchOrigin(req).then(r => r.text())); // 3) 直写 KV,并设置软/硬 TTL await EDGE_KV.put(key, JSON.stringify({ body, softExp: now + SOFT_TTL, hardExp: now + HARD_TTL }), { expiration: now + HARD_TTL }); return ok(body, false); } function ok(body: string, cached: boolean) { return new Response(body, { headers: { "Content-Type": "application/json", "X-Edge-Cache": cached ? "HIT" : "MISS" } }); } // 单飞模式防止热点键上的惊群效应 const inflight = new Map<string, Promise<string>>(); async function singleFlight(key: string, fn: () => Promise<string>) { if (inflight.has(key)) return inflight.get(key)!; const p = fn().finally(() => inflight.delete(key)); inflight.set(key, p); return p; } // 发射后不管的刷新 function refreshLater(key: string, req: Request) { // 特定平台的 waitUntil/queue;建议最小退避 (globalThis as any).waitUntil?.(singleFlight(key, () => fetchOrigin(req).then(r => r.text()) .then(body => EDGE_KV.put(key, JSON.stringify({ body, softExp: Math.floor(Date.now()/1000) + SOFT_TTL, hardExp: Math.floor(Date.now()/1000) + HARD_TTL }), { expirationTtl: HARD_TTL }))); }

这里的 single-flight 特别重要,热点键过期时,不会几百个请求同时回源,而是只让一个请求去拉数据,其他人等着拿结果,源站瞬间压力大减。

Redis 层:加抖动避免同步过期

Redis 里实现软 / 硬 TTL 也类似,但要多一步 TTL 抖动,比如本来硬 TTL 设 10 分钟,实际存的时候随机加 / 减 1-2 分钟。不然大量缓存同时过期,还是会引发 “雪崩”。

给个 Python 示例:

import json, random, time import redis r = redis.Redis() SOFT, HARD = 60, 600 def get_cache(key: str, loader): now = int(time.time()) raw = r.get(key) if raw: entry = json.loads(raw) if now <= entry["soft"]: # 新鲜数据 return entry["val"], True # 近过期概率性刷新 if random.random() < 0.1: _refresh_async(key, loader) if now <= entry["hard"]: return entry["val"], True # 允许返回过期数据 # 未命中或硬过期 val = loader() soft = now + SOFT + random.randint(-5, 5) hard = now + HARD + random.randint(-30, 30) r.setex(key, HARD, json.dumps({"val": val, "soft": soft, "hard": hard})) return val, False

避坑指南

分层缓存看着复杂,但只要避开几个坑,基本不会出问题。

别按 “用户 ID” 做缓存键

之前有个客户给个性化首页做缓存,键用的是 “user:123:home”,结果每个用户都是 miss,缓存等于白加,还浪费了一堆存储。后来改成按 “用户分段”—— 比如 “会员:华东区:home”,把同套餐同区域的用户归为一类,命中率直接从 5% 飙到 80%。

缓存头千万别漏

CDN 没 Cache-Control 头,它就会直接回源。新手可以先无脑加 max-age=60, stale-while-revalidate=600,再慢慢调参数。

别把边缘 KV 当数据库

边缘 KV 是缓存不是存储,写操作一定要落源站,再通过刷新机制同步到边缘。之前我们的客户试过在边缘直接写数据,结果不同区域数据不一致,排查了半天。

清除缓存别一刀切

全量清缓存等于给源站开闸,瞬间请求量能翻 10 倍。要用 Surrogate-Key 按标签清,比如改了某款商品,只清 product:123 的缓存,影响范围最小。

可观测性

缓存搭好不是结束,得知道它有没有用。在 Grafana 里加这 5 个面板,出问题能秒定位。

  1. 各层命中率(CDN、边缘 KV、Redis):低于 70% 就得调策略;
  2. 过期内容使用率:太高说明源站压力大,得加软 TTL;
  3. single-flight 并发数:突然飙升可能是热点键来了;
  4. 各区域延迟(p50/p95):看缓存对用户体验的实际影响;
  5. 错误导致的过期内容占比:太高说明源站不稳定。

总结

单一 Redis 能解决很多问题,但要撑住高并发、全球访问、动态内容,依赖分层架构 + 灵活策略的体系更为稳妥。CDN 扛静态,边缘 KV 扛动态,Redis 兜底,再配上软 / 硬 TTL、single-flight、抖动这些细节,真正做到源站稳了,用户快了,值班也能睡个安稳觉了。

如果刚开始试,不用一步到位,我们建议先搞 CDN + Redis 组合,跑顺了再加边缘层,成本低还见效快。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/26 20:44:52

C语言实现GBK到Unicode字符编码转换

GBK 到 Unicode 转换函数的设计与实现 在处理中文文本的底层系统开发中&#xff0c;字符编码转换是一个绕不开的核心问题。尤其是在嵌入式系统、跨平台应用或国际化&#xff08;i18n&#xff09;支持场景下&#xff0c;如何高效准确地将 GBK 编码的汉字转换为标准 Unicode&…

作者头像 李华
网站建设 2026/1/26 18:10:41

你真的会用Open-AutoGLM Phone吗?7个高效AI交互技巧99%人未掌握

第一章&#xff1a;Open-AutoGLM Phone的核心能力解析Open-AutoGLM Phone 是一款基于多模态大语言模型的智能终端系统&#xff0c;深度融合自然语言理解、语音交互与自动化任务执行能力。其核心架构依托于 GLM 大模型的上下文推理能力&#xff0c;结合设备端轻量化部署技术&…

作者头像 李华
网站建设 2026/1/30 5:13:25

手慢无!Open-AutoGLM源码下载地址及本地部署完整教程,一文搞定

第一章&#xff1a;Open-AutoGLM源码下载地址 获取 Open-AutoGLM 的源码是参与其开发与本地部署的第一步。该项目托管于主流开源平台&#xff0c;确保了社区协作的透明性与可访问性。 源码仓库位置 Open-AutoGLM 的官方源码托管在 GitHub 上&#xff0c;开发者可通过以下地址访…

作者头像 李华
网站建设 2026/1/26 20:23:22

Open-AutoGLM沉思平台重大更新预告(仅限官网注册用户获取的3项特权)

第一章&#xff1a;Open-AutoGLM沉思平台重大更新概览Open-AutoGLM沉思平台近日发布了里程碑式版本更新&#xff0c;全面增强其在自动化推理、模型微调与多模态交互方面的能力。本次升级聚焦于提升开发者体验与系统可扩展性&#xff0c;引入多项核心功能优化。全新异步任务调度…

作者头像 李华
网站建设 2026/1/26 21:23:05

现在不部署就落后了:Open-AutoGLM本地运行的5大核心优势与实操步骤

第一章&#xff1a;现在不部署就落后了&#xff1a;Open-AutoGLM本地运行的5大核心优势与实操步骤 在生成式AI快速演进的当下&#xff0c;将大语言模型本地化部署已成为企业与开发者提升效率、保障数据安全的关键路径。Open-AutoGLM作为支持自动化任务理解与执行的开源模型&…

作者头像 李华
网站建设 2026/1/27 1:47:48

【Java毕设源码分享】基于springboot+vue的本科实践教学管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华