欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > 如何保证缓存和数据库的双写一致性

如何保证缓存和数据库的双写一致性

2025/6/20 2:21:15 来源:https://blog.csdn.net/2508_90580492/article/details/148746535  浏览:    关键词:如何保证缓存和数据库的双写一致性

一、一致性分级与适用场景

级别延迟范围适用场景代表方案
强一致性0ms金融账户、库存扣减分布式锁+同步双写
最终一致性10ms-10s商品详情、用户信息延迟双删、消息队列
弱一致性>10s文章阅读量、排行榜定时全量刷新

二、经典解决方案详解

1. Cache-Aside Pattern(旁路缓存)

流程

App Cache DB 读请求 返回数据 查询数据 返回数据 写入缓存 alt [缓存命中] [未命中] 写数据 删除缓存 App Cache DB

问题:先写库后删缓存的间隙可能读到旧数据
优化:异步延迟双删(解决并发读写脏数据)


2. Write-Through(穿透写)

架构

应用
Cache
Write Handler
DB
  • 所有写请求先到Cache,由Cache同步写DB
  • 优点:确保缓存永不过期
  • 缺点:写延迟高(需等待DB完成)

3. Write-Behind(异步写)

流程

App Cache DB 写数据 立即响应 批量写回 loop [异步批处理] App Cache DB

特点

  • 高性能(写操作≈内存速度)
  • 数据可能丢失(宕机时缓存未刷盘)
  • 需配合WAL日志(如Redis AOF)

三、高并发场景下的精控方案

4. 分布式锁强一致
// Redisson实现示例
public void updateData(Data newData) {RLock lock = redisson.getLock("DATA_LOCK:" + newData.id);try {lock.lock();  // 获取分布式锁db.update(newData);   // 更新数据库cache.delete(newData.id); // 删除缓存} finally {lock.unlock();}
}

缺陷:性能下降(吞吐量≈DB单点写入能力)


5. 版本号控制(乐观锁)

操作步骤

  1. 数据中增加版本号字段 version
  2. 更新时校验版本号:
    UPDATE table SET value=#{value}, version=version+1 
    WHERE id=#{id} AND version=#{oldVersion}
    
  3. 若更新失败,重试或回滚缓存

6. Binlog监听同步(最终一致)
Binlog
消息
MySQL
Canal
RocketMQ
缓存更新Worker
Redis

优势

  • 彻底解耦应用层
  • 支持多级缓存同步
    时延:100ms-2s(取决于MQ堆积)

四、特殊问题解决方案

7. 缓存删除失败补偿机制
失败
成功
失败
删除缓存
记录删除失败Key
定时任务
读取失败队列
重试删除
移除队列
报警+人工介入

关键参数

  • 首次重试:1s后
  • 指数退避:最大重试5次
  • 死信处理:NACK后持久化存储

8. 热点Key并发重建

问题:缓存失效瞬间大量请求击穿DB
解法

// 使用Redis SETNX 互斥锁
public Data getData(String key) {Data data = cache.get(key);if (data == null) {String lockKey = "LOCK:" + key;if (redis.setnx(lockKey, 1)) { // 获取锁redis.expire(lockKey, 3);  // 避免死锁data = db.query(key);      // 查库cache.set(key, data, 30);  // 写缓存redis.del(lockKey);        // 释放锁} else {Thread.sleep(50);          // 等待后重试return getData(key);       // 递归调用}}return data;
}

五、方案选型决策树

graph TDA[业务要求强一致?] -->|是| B[分布式锁]A -->|否| C{写频率}C -->|高频写| D[Write-Behind+WAL]C -->|低频写| E[Cache-Aside+延迟双删]C -->|批量写| F[Binlog监听]

六、工业级配置参数参考

组件关键配置项推荐值作用
Redismaxmemory-policyvolatile-lfu内存淘汰策略
Canalcanal.mq.retries5MQ发送重试次数
RedissonlockWatchdogTimeout30000看门狗超时(ms)
本地缓存Caffeine.expireAfterWrite5s防雪崩时间窗口

七、容灾设计

  1. 降级开关
    // 配置中心动态开关
    if (ConfigService.getBool("DISABLE_CACHE")) {return db.query(key); // 直接读库
    }
    
  2. 缓存污染防护
    • 空值缓存:SET key null 5s 防穿透
    • 布隆过滤器:拦截非法Key请求
  3. 多级熔断
    指标阈值动作
    DB QPS>5000关闭缓存更新
    缓存Miss率>40%开启本地缓存
    平均响应时间>200ms跳过缓存直读DB

你想要的我全都有:https://pan.q删掉憨子uark.cn/s/75a5a07b45a2

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词