Redis 和 Caffeine 构建的多级缓存,如何保持数据一致性?

文章目录

      • [一、 核心同步链路:主动失效机制](#一、 核心同步链路:主动失效机制)
        • [1. 消息队列 (MQ) 广播通知](#1. 消息队列 (MQ) 广播通知)
        • [2. Binlog 异构同步](#2. Binlog 异构同步)
        • [3. Redis Pub/Sub 订阅](#3. Redis Pub/Sub 订阅)
      • [二、 多重兜底与容错策略](#二、 多重兜底与容错策略)
        • [1. 差异化 TTL (过期时间)](#1. 差异化 TTL (过期时间))
        • [2. 本地消息表与重试补偿](#2. 本地消息表与重试补偿)
        • [3. 互斥锁与双删策略](#3. 互斥锁与双删策略)
      • [三、 总结:不同场景的选型决策](#三、 总结:不同场景的选型决策)

在分布式系统中,使用 Caffeine (L1 本地缓存) 与 Redis (L2 分布式缓存) 构建多级缓存架构,其核心挑战在于如何解决"数据孤岛"问题,即当数据库更新时,如何确保各节点本地内存中的数据与中心库保持一致。

以下是针对该架构的深度一致性治理方案:


一、 核心同步链路:主动失效机制

为了保证数据的实时性,通常采用**"删除"而非"更新"**的策略,以避免并发写入导致的脏数据。

1. 消息队列 (MQ) 广播通知

这是大厂最常用的生产级方案。

  • 流程 :当应用执行写操作更新数据库后,向消息队列(如 RocketMQ)发送一条广播消息。各业务节点订阅该主题,收到消息后立即清除自身本地的 Caffeine 缓存。
  • 优势:解耦写操作与缓存失效逻辑,利用 MQ 的重试机制提高补偿成功率。
  • 注意:在极端高并发下,需考虑 MQ 延迟导致的瞬时数据不一致。
2. Binlog 异构同步

通过监听数据库底层日志实现缓存的自动化清理。

  • 流程 :使用中间件(如 Canal)伪装成数据库从节点,实时解析 MySQL 的 Binlog 。一旦监控到目标表发生 UPDATE 或 DELETE,同步组件发送失效信号至 Redis 并广播至各节点清除 Caffeine。
  • 优势:对业务代码零侵入,确保了数据库与缓存操作的原子性逻辑一致。
3. Redis Pub/Sub 订阅
  • 流程 :利用 Redis 自带的发布/订阅功能,写操作后 publish 变更消息,各节点监听并清理 L1 缓存。
  • 局限性:Redis 的 Pub/Sub 是"发后即忘"模式,若节点宕机或网络抖动,会导致消息丢失且无法回溯。

二、 多重兜底与容错策略

1. 差异化 TTL (过期时间)
  • 配置建议:L1 本地缓存的过期时间应显著短于 L2 分布式缓存(例如:L1 设置 1-5 分钟,L2 设置 30 分钟以上)。
  • 价值 :即使主动失效机制因网络波动失败,本地缓存也会在极短时间内失效,自动从数据库或 Redis 加载最新值,实现最终一致性。
2. 本地消息表与重试补偿
  • 若广播失效,可在数据库中记录一张本地消息表。
  • 通过定时任务扫描未成功处理的失效任务进行重试,直至所有节点确认失效或达到重试上限后人工介入。
3. 互斥锁与双删策略
  • 延迟双删:在更新数据库前删除一次 Redis,更新后再删除一次(并延迟一段时间),以降低读取旧值并回写缓存的风险。
  • 分布式锁:对于极高一致性要求的业务(如金融对账),在写操作时加锁,强制让读操作在失效完成前进入等待或直接穿透至数据库。

三、 总结:不同场景的选型决策

场景 推荐方案 核心理由
高并发、高吞吐 MQ 广播 + 差异化 TTL 性能损耗小,具备良好的削峰填谷能力。
低侵入、自动化 Binlog 同步 (Canal) 业务方无需关注缓存逻辑,适合存量系统改造。
极致一致性 分布式锁 + 数据库强制读 牺牲部分吞吐量以换取数据绝对准确。

架构建议 :在实际工程中,建议采用 "数据库更新 + MQ 异步失效 + 极短 TTL 兜底" 的组合拳。这样既保证了正常情况下的微秒级同步,也通过过期机制解决了网络异常下的数据滞后问题。

在你之前负责的业务中,对于涉及到"钱"或"补贴金额"的对账场景,是否除了 Job 定时校验外,也引入了类似的实时同步链路来规避风险?

相关推荐
时间的拾荒人1 小时前
Redis 集合类型详解:Set 与 Zset
redis·缓存·面试
Pniubi1 小时前
MySQL靠什么实现事务的?事务隔离级别有哪些?
java·数据库·mysql
数据库小学妹2 小时前
pgbouncer 事务池:prepared statement、临时表与会话状态
数据库·后端·postgresql
鶴哥只手遮天3 小时前
《Redis 8.10.3 深度剖析》系列 ·第 17 章. 一个迟到十六年的类型
redis·后端·开源
Lucifer三思而后行3 小时前
最近折腾了一下金仓数据库的备份恢复
数据库·备份恢复
草莓熊Lotso4 小时前
【C++ 基于微服务的即时通讯系统】文件存储子服务实战:UUID生成、文件IO封装与全接口单元测试
开发语言·网络·数据库·c++·微服务·架构·单元测试
进击的荆棘5 小时前
MySQL——库的操作
数据库·mysql
2601_967980115 小时前
“小程序·云开发”上线 助力开发者的高效利器
数据库·存储管理·小程序云开发·云函数·开发者工具
zhangjw345 小时前
1-9 SELECT 查询基础:where、group by、having、order by、limit offset
数据库·postgresql·pg数据库