在高并发场景下,每个接口请求都穿透到数据库是不现实的。缓存作为提升性能的利器,使用得当可将响应时间从百毫秒级降到毫秒级。但缓存引入了数据一致性复杂性,需要在性能和正确性间找到平衡。本文按分层缓存思路逐一分析。
HTTP 协议级缓存
HTTP 协议本身提供完整缓存机制,通过 Cache-Control、ETag 和 Last-Modified 等头部字段实现。对于不频繁变化的资源接口,设置「Cache-Control: max-age=300」可让浏览器在五分钟内直接使用本地缓存,不再向服务端发起请求。
ETag 机制实现条件请求:服务端在响应中返回资源标识,客户端下次请求携带「If-None-Match」头部,服务端比对后决定返回完整内容还是 304 状态码。数据未变化时大幅减少传输量。公开只读接口应优先利用 HTTP 缓存,成本最低且效果显著。
CDN 边缘缓存
对于面向全国乃至全球用户的接口,CDN 缓存能将响应缓存在离用户最近的节点。配置时需区分可缓存和不可缓存的接口路径,GET 请求的静态数据接口适合开启 CDN 缓存,POST 请求和个性化数据接口必须排除。
CDN 缓存失效操作要注意控制粒度。批量刷新会导致命中率骤降引发回源风暴。建议按内容变更触发精准刷新,配合较长 TTL 策略,让节点在自然过期前持续服务。同时监控命中率,低于预期时检查缓存规则配置。
应用层本地缓存
应用进程内的本地缓存访问速度最快,无需网络开销。适合存放体积小、读取频繁且变更极少的数据,如配置字典、枚举列表等。实现可选择 Caffeine 等高性能缓存库,设置最大容量和过期时间防止内存无限增长。
本地缓存难点在于多实例间数据一致性。某实例更新缓存后其他实例仍持有旧值。一致性要求不高的场景可接受短暂不一致;强一致性场景需借助消息广播或分布式锁同步各实例缓存状态,但这会增加系统复杂度。
分布式缓存层
Redis 是分布式缓存的事实标准。接口场景中将数据库查询结果序列化为 JSON 存入 Redis,以请求参数和查询条件拼接成缓存键。设置合理 TTL 让缓存在业务可接受窗口内自动过期,避免手动管理失效逻辑的复杂性。
缓存键设计要避免冲突和过长。建议采用「接口名:版本:参数哈希」结构,既保证唯一性又控制键长度。务必对空结果也做缓存防止穿透,同时设置互斥锁或布隆过滤器避免大量请求同时回源造成击穿。
一致性保障与监控
缓存引入意味着同一份数据存在多个副本,更新时需按既定顺序操作缓存和数据库。常见做法是先更新数据库再删除缓存,下次查询时自然回源重建。并发场景下可能出现短暂不一致,但对多数业务可接受。
监控方面需关注命中率、平均响应时间和慢查询比例。命中率低于预期通常是策略不当或数据变更频繁。建立完善的监控面板,将关键指标纳入告警体系,才能在缓存异常时快速响应。