缓存失效需采用“最终一致+本地兜底+精准触发”策略:按数据类型分类处理,用带机房id、序号、操作类型的轻量消息保序广播,辅以本地布隆过滤器和定期冷加载校验,禁用通配符广播并隔离通道。

缓存失效处理在异地多活架构中不能靠“单点广播”或“轮询拉取”,必须结合数据一致性边界、传播时效性与故障隔离能力来设计。核心思路是:**不追求强一致的实时失效,而是用“最终一致+本地兜底+精准触发”组合保障业务正确性。**
明确缓存失效的粒度与范围
不是所有缓存都适合跨机房广播失效。需先分类:
- 用户会话类缓存(如 token、session):归属地强绑定,只在写入机房失效,其他机房通过过期时间(TTL)自然淘汰,不广播;
- 配置类缓存(如开关、路由规则):变更频次低、影响面广,适合走强一致广播通道(如基于 Redis Pub/Sub + 全局有序消息队列);
-
业务实体缓存(如商品详情、用户资料):采用“写穿透 + 主键失效广播”模式——仅当主库在 A 机房更新后,向所有机房广播
invalidate:user:1001这类确定性指令,而非模糊的“刷新用户缓存”; - 聚合类/计算类缓存(如排行榜、统计摘要):不主动失效,改用定时重建 + 版本号校验,避免广播风暴。
用带序号和来源标识的轻量消息做失效广播
直接用 Redis 的 PUB/SUB 或 Kafka 广播原始 key 存在风险:乱序、重复、丢失。推荐做法:
- 每条失效消息携带三项元数据:机房ID(source_zone)、逻辑时钟序号(seq_no)、操作类型(DEL/INVALIDATE);
- 各机房消费者按
source_zone + seq_no做本地去重与保序,跳过已处理的旧序号消息; - 不依赖网络层保证顺序,而由应用层用单线程消费 + 内存序列号窗口(如滑动窗口大小 1024)实现低成本保序;
- 关键缓存 key 失效后,加一层本地布隆过滤器标记“近期被删过”,防止缓存击穿时大量回源。
本地兜底策略比广播更关键
广播只是辅助,真正防错靠本地机制:
- 所有读缓存操作前,先检查本地是否收到该 key 的最新失效通知(查本地内存标记或 Redis 中的
invalidated_keys_bloom); - 若命中失效标记,强制回源查 DB,并写入新值——此时即使广播延迟 5 秒,也只多一次 DB 查询,不影响结果正确性;
- 为防广播完全中断,每个机房定期(如 30 秒)扫描本地高频缓存 key 的最后更新时间,若超阈值(如 2 分钟无 DB 更新记录),自动触发一次冷加载校验;
- 对库存、余额等强一致性场景,缓存本身就不存,直接走数据库 + 行锁或分布式锁,缓存只作非关键路径的展示加速。
避免跨机房广播引发雪崩的实操要点
广播不是万能解药,配置不当反而放大风险:
- 禁用通配符广播(如
invalidate:user:*),只允许精确 key 或预定义 tag(如invalidate:tag:product_promo); - 广播通道与业务流量物理隔离:使用独立 Kafka topic / RocketMQ group,带限流熔断(如单机房每秒最多处理 500 条失效消息);
- 失效消息体保持极简——只含 key 和时间戳,不附带 value 或上下文,减少序列化开销与传输延迟;
- 上线前用混沌测试验证:手动延迟/丢弃某机房的失效消息,确认业务仍能通过兜底逻辑返回正确结果。











