当前位置:

首页 > 编程开发 > Java中怎么保证缓存一致性

Java中怎么保证缓存一致性

方案一:更新缓存,更新数据库这种方式可轻易排除,因为如果先更新缓存成功,但是数据库更新失败,则肯定会造成数据不一致。方案二:更新数据库,更新缓存这种缓存更新策略俗称双写,存在问题是:并发更新数据库场景下,会将脏数据刷到缓存updateDB();updateRedis();举例:如果在两个操作之间数据库和缓存又被后面请求修改,此时再去更新缓存已经是过期数据了。方案三:删除缓存,更新数据库存在问题:更新数据库之前,若有查询请求,会将脏数据刷到缓存deleteRedis();updateDB();举例:如果在两

本文目录

    方案一:更新缓存,更新数据库

    这种方式可轻易排除,因为如果先更新缓存成功,但是数据库更新失败,则肯定会造成数据不一致。

    方案二:更新数据库,更新缓存

    这种缓存更新策略俗称双写,存在问题是:并发更新数据库场景下,会将脏数据刷到缓存

    updateDB();
    updateRedis();

    举例:如果在两个操作之间数据库和缓存又被后面请求修改,此时再去更新缓存已经是过期数据了。

    Java中怎么保证缓存一致性

    方案三:删除缓存,更新数据库

    存在问题:更新数据库之前,若有查询请求,会将脏数据刷到缓存

    deleteRedis();
    updateDB();

    举例:如果在两个操作之间发生了数据查询,那么会有旧数据放入缓存。

    Java中怎么保证缓存一致性

    该方案会导致请求数据不一致

    如果同时有一个请求A进行更新操作,另一个请求B进行查询操作。那么会出现如下情形:

    • 请求A进行写操作,删除缓存

    • 请求B查询发现缓存不存在

    • 请求B去数据库查询得到旧值

    • 请求B将旧值写入缓存

    • 请求A将新值写入数据库

    上述情况就会导致不一致的情形出现。而且,如果不采用给缓存设置过期时间策略,该数据永远都是脏数据。

    方案四:更新数据库,删除缓存

    存在问题:在更新数据库之前有查询请求,并且缓存失效了,会查询数据库,然后更新缓存。如果在查询数据库和更新缓存之间进行了数据库更新的操作,那么就会把脏数据刷到缓存

    updateDB();
    deleteRedis();

    举例:如果在查询数据库和放入缓存这两个操作中间发生了数据更新并且删除缓存,那么会有旧数据放入缓存。

    Java中怎么保证缓存一致性

    假设有两个请求,一个请求A做查询操作,一个请求B做更新操作,那么会有如下情形产生

    • 缓存刚好失效

    • 请求A查询数据库,得一个旧值

    • 请求B将新值写入数据库

    • 请求B删除缓存

    • 请求A将查到的旧值写入缓存

    如果发生上述情况,确实是会发生脏数据。但是发生上述情况有一个先天性条件,就是写数据库操作比读数据库操作耗时更短

    不过数据库的读操作的速度远快于写操作的

    因此这一情形很难出现。

    方案对比

    方案1和方案2的共同缺点:

    并发更新数据库场景下,会将脏数据刷到缓存,但一般并发写的场景概率都相对小一些;

    线程安全角度,会产生脏数据,比如:

    • 线程A更新了数据库

    • 线程B更新了数据库

    • 线程B更新了缓存

    • 线程A更新了缓存

    方案3和方案4的共同缺点:

    不管采用哪种顺序,2种方式都是存在一些问题的:

    • 主从延时问题:不管是先删除还是后删除,数据库主从延时可能导致脏数据的产生。

    • 缓存删除失败:如果缓存删除失败,则都会产生脏数据。

    问题解决思路:延迟双删,添加重试机制,下面介绍!

    更新缓存还是删除缓存?

    • 1.更新缓存缓存需要有一定的维护成本,而且会存在并发更新的问题

    • 2.写多读少的情况下,读请求还没有来,缓存以及被更新很多次,没有起到缓存的作用

    • 3.放入缓存的值可能是经过复杂计算的,如果每次更新,都计算写入缓存的值,浪费性能的

    删除缓存优点:简单、成本低,容易开发;缺点:会造成一次cache miss

    如果更新缓存开销较小并且读多写少,基本不会有写并发的时候可以才用更新缓存,否则通用做法还是删除缓存。

    总结

    方案问题问题出现概率推荐程度
    更新缓存 -> 更新数据库为了保证数据准确性,数据必须以数据库更新结果为准,所以该方案绝不可行大不推荐
    更新数据库 -> 更新缓存并发更新数据库场景下,会将脏数据刷到缓存并发写场景,概率一般写请求较多时会出现不一致问题,不推荐使用。
    删除缓存 -> 更新数据库更新数据库之前,若有查询请求,会将脏数据刷到缓存并发读场景,概率较大读请求较多时会出现不一致问题,不推荐使用
    更新数据库 -> 删除缓存在更新数据库之前有查询请求,并且缓存失效了,会查询数据库,然后更新缓存。如果在查询数据库和更新缓存之间进行了数据库更新的操作,那么就会把脏数据刷到缓存并发读场景&读操作慢于写操作,概率最小读操作比写操作更慢的情况较少,相比于其他方式出错的概率小一些。勉强推荐。

    推荐方案

    延迟双删

    采用更新前后双删除缓存策略

    public void write(String key,Object data){
      redis.del(key);
         db.update(data);
         Thread.sleep(1000);
         redis.del(key);
     }
    • 先淘汰缓存

    • 再写数据库

    • 休眠1秒,再次淘汰缓存

    大家应该评估自己的项目的读数据业务逻辑的耗时。然后写数据的休眠时间则在读数据业务逻辑的耗时基础上即可。

    这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。

    问题及解法:

    1、同步删除,吞吐量降低如何处理

    将第二次删除作为异步的,提交一个延迟的执行任务

    2、解决删除失败的方式:

    添加重试机制,例如:将删除失败的key,写入消息队列;但对业务耦合有些严重;

    Java中怎么保证缓存一致性

    延时工具可以选择:

    最普通的阻塞Thread.currentThread().sleep(1000);

    Jdk调度线程池,quartz定时任务,利用jdk自带的delayQueue,netty的HashWheelTimer,Rabbitmq的延时队列,等等

    实际场景

    我们有个商品中心的场景,是读多写少的服务,并且写数据会发送MQ通知下游拿数据,这样就需要严格保证缓存和数据库的一致性,需要提供高可靠的系统服务能力。

    写缓存策略

    • 缓存key设置失效时间

    • 先DB操作,再缓存失效

    • 写操作都标记key(美团中间件)强制走主库

    • 接入美团中间件监听binlog(美团中间件)变化的数据在进行兜底,再删除缓存

    Java中怎么保证缓存一致性

    读缓存策略

    • 先判断是否走主库

    • 如果走主库,则使用标记(美团中间件)查主库

    • 如果不是,则查看缓存中是否有数据

    • 缓存中有数据,则使用缓存数据作为结果

    • 如果没有,则查DB数据,再写数据到缓存

    Java中怎么保证缓存一致性

    注意

    关于缓存过期时间的问题

    如果缓存设置了过期时间,那么上述的所有不一致情况都只是暂时的。

    但是如果没有设置过期时间,那么不一致问题就只能等到下次更新数据时解决。

    所以一定要设置缓存过期时间。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Java
    相关文章 更多
    Java单元测试入门:使用JUnit 5编写第一个测试用例
    Java单元测试入门:使用JUnit 5编写第一个测试用例

    面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

    Java变量未初始化报错解析:局部变量与成员变量默认值差异
    Java变量未初始化报错解析:局部变量与成员变量默认值差异

    深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

    详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

    Java中final与static final常量的定义及初始化规则
    Java中final与static final常量的定义及初始化规则

    深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

    Java抽象方法与接口方法的区别及选型建议
    Java抽象方法与接口方法的区别及选型建议

    深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

    Java实现HTTP请求与JSON解析的完整代码示例
    Java实现HTTP请求与JSON解析的完整代码示例

    本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

    Java递归出现StackOverflowError的原因分析及栈空间优化方案
    Java递归出现StackOverflowError的原因分析及栈空间优化方案

    详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

    Java空指针异常(NPE)的代码排查与修复实例
    Java空指针异常(NPE)的代码排查与修复实例

    针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。