侧边栏壁纸
博主头像
博客技术 博主等级

行动起来,活在当下

  • 累计撰写 42 篇文章
  • 累计创建 4 个标签
  • 累计收到 3 条评论

目 录CONTENT

文章目录

如何保证Redis缓存与数据库的数据一致性

Administrator
2025-02-17 / 0 评论 / 1 点赞 / 16 阅读 / 0 字

在分布式系统中,Redis作为缓存与数据库协同工作时,数据一致性是高频面试题。以下从核心场景分析、解决方案及优化策略展开说明:

一、数据不一致的核心场景

  1. 读写并发

    • 纯读操作:仅查询不会导致不一致。

    • 读写并发:当修改数据(写)与查询数据(读)同时发生时,若操作顺序不当,缓存与数据库数据可能不一致。


二、写策略选择:删除缓存 vs 更新缓存

  1. 直接删除缓存的优势

    • 逻辑简单:仅需删除缓存,后续请求触发被动加载数据库最新数据。

    • 避免复杂计算:更新缓存可能涉及业务逻辑处理(如聚合统计),删除操作更轻量。

    • 规避多线程竞争:并发更新缓存可能导致数据覆盖或脏数据。

  2. 更新缓存的弊端

    • 数据耦合风险:缓存层与业务逻辑耦合度高,维护成本增加。

    • 资源浪费:高频更新但低频访问的数据频繁写入缓存,占用内存。


三、操作顺序:先操作数据库 vs 先操作缓存

方案1:先删缓存,再更新数据库(延迟双删)

  • 问题场景
    线程A删除缓存后更新数据库(网络延迟),线程B查询旧数据并回填缓存,导致后续请求读取到旧数据。

  • 解决方案:延迟双删

    1. 线程A删除缓存 → 更新数据库 → 延迟数百毫秒 → 再次删除缓存。

    2. 延迟目的:确保线程B的旧数据回填已完成,二次删除清空脏数据。

    3. 缺点:短暂数据不一致窗口,需业务容忍最终一致性。

方案2:先更新数据库,再删缓存

  • 优势
    线程A先更新数据库后删缓存,线程B查询时触发缓存重建,数据一致性更高。

  • 极端问题:若缓存删除失败,需通过重试机制保证最终一致。


四、优化策略:解耦与异步保障

  1. 重试机制

    • MQ异步重试:删除缓存失败时,发送消息至MQ,消费者监听并重试删除。

    • 本地重试表:记录失败操作,定时任务扫描重试。

  2. 基于Binlog的最终一致性(Canal监听)

    • Canal原理:模拟MySQL主从复制,解析Binlog日志获取数据变更。

    • 流程

      1. 数据库更新 → Canal捕获变更 → 通知客户端(如Spring Boot应用)。

      2. 客户端收到通知 → 删除或更新Redis。

    • 优势:业务代码解耦,通过中间件保证数据同步。


五、一致性的权衡:AP vs CP

  • 强一致性(CP):通过分布式锁保证操作原子性,但牺牲性能,不适用于高并发场景。

  • 最终一致性(AP):接受短暂不一致,通过延迟双删、异步监听等手段实现最终一致,适用于大多数业务场景。


六、总结回答

在面试中可结构化回答:

  1. 问题分析:读写并发是导致不一致的主因。

  2. 策略选择:推荐先更新数据库再删缓存,结合延迟双删。

  3. 容错机制:通过MQ重试或Canal监听Binlog解耦处理。

  4. 业务权衡:根据场景选择最终一致性,平衡性能与数据准确性。

最佳回答:

"在高并发场景下,我们采用‘先更新数据库,再删除缓存’策略,并结合延迟双删避免并发读写导致的不一致。针对极端删除失败情况,通过Canal监听Binlog异步触发缓存删除,或MQ重试机制保证最终一致。这种方案在保证系统性能的同时,最大限度减少数据不一致窗口期。"

1

评论区