各位朋友,今天咱们来摆一摆CDN里头一个特别容易被忽略、但又特别要命的配置项——缓存键,你可能会想:“缓存键?不就是URL吗?有啥好讲的?”嘿,要是这么想,那你可就踩了大坑了,我见过太多网站,花了大价钱买了CDN,结果因为缓存键没配对,要么用户看到别人的隐私,要么缓存跟没开一样,钱白花了还挨骂,今天我就用四川话(哦不,大白话)给你把这个东西讲透。
啥是缓存键?说白了就是快递单号
咱们先理解一下CDN缓存的本质,当一个用户访问你的网站,CDN边缘节点会先看自己有没有这个文件,怎么看?就是根据一个“标识”去查表,这个标识,就是缓存键,它就像一个快递单号:CDN的服务器就是快递中转站,缓存的内容就是包裹,每个请求到了,CDN先看单号(缓存键),如果仓库里已经有这个单号的包裹,就直接给你;如果没有,就回源站去取,然后存下来,下次别人再用这个单号来取,就不用再去源站了。
最基础的缓存键,就是URL的路径,比如https://example.com/pic/1.jpg,这个路径就是单号。—问题来了,如果同一个路径,因为不同的请求头(比如语言、设备、登录状态)需要返回不同的内容,那这个单号就“撞车”了,你想想,两个人用同一个单号,快递员能知道该给哪个包裹吗?缓存键必须能唯一标识一个响应内容。
原理:缓存键到底由哪些东西组成?
一个典型的CDN平台(比如Cloudflare、阿里云CDN等),缓存键可以由以下几个部分拼接而成:

缓存键配置搞不对,CDN再快也白费—老司机手把手教你避坑
- Host:域名,不同域名下的同一个路径,内容是独立的。
- URL路径:例如
/index.html或/api/user。 - URL参数(Query String):例如
?page=2&lang=zh。 - 请求头(Headers):比如
Accept-Language(语言偏好)、User-Agent(设备类型)、Authorization(令牌)。 - Cookie:某些场景下需要根据用户登录态区分内容。
- 协议:HTTP和HTTPS有时也会被区分。
CDN会把这些信息拼成一个字符串,然后哈希一下,作为缓存键。host=example.com+path=/product+lang=zh+device=mobile → 哈希后存入缓存。
关键点:缓存键决定了“什么情况下CDN认为是同一个请求”,如果你把不该加的要素加进去了,会导致缓存碎片化——每个请求都不同,命中率为0,回源率飙升,如果你把该加的要素漏了,就会导致“缓存串门”——用户A看到用户B的数据。
应用场景:什么时候需要折腾缓存键?
场景1:多语言网站
你的网站有中文版和英文版,通过URL参数?lang=zh和?lang=en区分,如果你把缓存键配置成“忽略所有参数”,那么无论是什么语言的用户,访问/help都会返回同一个缓存内容——可能全是中文,或者全是英文,乱套了,正确的做法是:把lang参数加入缓存键。
场景2:用户登录后的个性化页面
例如一个电商网站的“我的购物车”页面,URL是/cart,但是登录用户A和用户B看到的内容完全不同,如果你只用URL做缓存键,那么用户A访问后,CDN缓存了A的购物车内容,用户B再访问,就会看到A的购物车——这是严重的安全事故!解决方式:把Cookie中的session_id或者Authorization头加入缓存键,或者干脆对需要个性化的页面禁用CDN缓存(但这样性能差),更好的做法是:使用“私有缓存”策略,让CDN区分用户。
场景3:A/B测试或动态版本控制
有些网站通过URL参数?v=1.0来控制页面版本,如果你没把这个参数加入缓存键,那么你发布新版本后,老用户可能一直看到旧页面,正确做法是:把版本号相关的参数作为缓存键的一部分,或者使用Cache-Control: no-cache强制回源。
案例说明:一个惨痛的教训
我之前帮一个在线教育平台做优化,他们的课程详情页URL结构是/course/123,但是同一个课程,针对会员和非会员显示的购买按钮不一样,他们傻乎乎地只用了URL做缓存键,结果没配置任何其他条件,上线第一天,大量免费用户访问了课程页后,CDN缓存了“免费用户看到的页面”(包含“立即购买”按钮),然后会员用户访问时,竟然也看到了“立即购买”按钮,点进去发现价格不对,客服电话被打爆。
排查后发现,缓存键漏掉了Cookie中表示会员身份的字段,后来我把Cookie: is_vip加入缓存键,并且对会员页面设置了较短的缓存时间(比如60秒),问题解决,但代价是:一天内回源率从5%飙到了35%,因为每个会员的请求都不同(即使同一个会员短时间内也不会重复访问同一页面?注意:这里如果会员很多,缓存键加了用户ID,那几乎每个请求都是新的,缓存基本没用,所以更合理的做法是:对于需要区分登录态但内容不极其个性化的页面,可以采用“页面级缓存+后端动态片段”,比如把会员专属信息通过AJAX异步加载,主页面仍然可以公用缓存。
这个案例告诉我们:缓存键不是加得越多越好,也不是越少越好,而是要精准匹配内容的差异性。
常见误区纠正
误区1:“缓存键就是URL,其他全忽略”
这是最普遍的错误,很多默认配置是忽略所有查询参数,如果你的网站有参数区分内容(比如分页、排序、语言),那必须把相关参数加入缓存键,但另一方面,有些参数是没意义的,比如?utm_source=facebook这样的追踪参数,如果不忽略,会导致同一个页面产生无数缓存副本,浪费空间,所以正确做法是:只将有意义的参数加入缓存键,忽略其他无用参数,大多数CDN支持“保留指定参数”或“忽略指定参数”的配置。
误区2:“缓存键里加了Cookie就安全了”
不一定,如果你把整个Cookie头都加进去,那用户的每一次访问(即使同一个用户多次刷新)可能因为Cookie中的_ga等统计字段变化而产生不同的缓存键,导致缓存完全失效,正确做法:只提取必要的Cookie字段,比如session_id或者token,很多CDN支持“高级缓存键”功能,可以用正则或规则提取指定字段。
误区3:“动态内容不能用CDN缓存”
很多开发者认为只要页面有动态数据(比如用户昵称),就完全不能缓存,其实可以通过缓存键+边缘计算的组合来解决,页面主体的HTML可以是缓存通用的,但用户昵称通过JavaScript异步从API获取,或者在CDN边缘节点上用Edge Workers根据Cookie动态注入,这样缓存键仍然可以只用URL+少数参数,而个性化部分后加载。
误区4:忽视“Host”和“协议”
如果你的网站同时支持http://和https://不同(比如HTTPS下强制使用安全资源),那么协议应该加入缓存键,同样,如果你有多个域名指向同一个源站,但返回的内容不同(比如www.example.com和m.example.com),就需要用Host区分。
总结一下
缓存键配置,本质上是在回答一个问题:“什么样子的两个请求,内容是一样的?” 回答对了,CDN性能翻倍,用户爽,源站轻松,回答错了,轻则缓存利用率低、回源压力大,重则泄露隐私、业务瘫痪。
建议你在调试CDN时,先手动构造几个不同请求,看看CDN是否返回了错误的内容,可以用浏览器的开发者工具,查看Response Header中的X-Cache(是否命中)和Age(缓存时间),再配合后端的日志,很容易定位问题。
最后送你一句老司机的口诀:静态文件路径直取,动态内容参数精取,用户隐私慎取,无用参数略取。 搞懂了缓存键,你的CDN才能真正“飞”起来。
发表评论