返回顶部
首页 > 资讯 > 精选 >Java并发编程数据库与缓存数据一致性方案是什么
  • 750
分享到

Java并发编程数据库与缓存数据一致性方案是什么

2023-06-29 20:06:29 750人浏览 薄情痞子
摘要

本文小编为大家详细介绍“Java并发编程数据库与缓存数据一致性方案是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“java并发编程数据库与缓存数据一致性方案是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧

本文小编为大家详细介绍“Java并发编程数据库缓存数据一致性方案是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“java并发编程数据库与缓存数据一致性方案是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

一、序言

分布式并发系统中,数据库与缓存数据一致性是一项富有挑战性的技术难点。假设有完善的工业级分布式事务解决方案,那么数据库与缓存数据一致性便迎刃而解,实际上,目前分布式事务不成熟。

二、不同的声音

在数据库与缓存数据一致解决方式中,有各种声音。

  • 先操作数据库后缓存还是先缓存后数据库

  • 缓存是更新还是删除

1、操作的先后顺序

在并发系统中,数据库与缓存双写场景下,为了追求更大的并发量,操作数据库与缓存显而易见不会同步进行。前者操作成功后者以异步的方式进行。

关系型数据库作为成熟的工业级数据存储方案,有完善的事务处理机制,数据一旦落盘,不考虑硬件故障,可以负责任的说数据不会丢失。

所谓缓存,无非是存储在内存中的数据,服务一旦重启,缓存数据全部丢失。既然称之为缓存,那么时刻做好了缓存数据丢失的准备。尽管Redis有持久化机制,是否能够保证百分之百持久化?Redis将数据异步持久化到磁盘有不可,缓存是缓存,数据库是数据库,两个不同的东西。把缓存当数据库使用是一件极其危险的事情。

从数据安全的角度来讲,先操作数据库,然后以异步的方式操作缓存,响应用户请求。

2、处理缓存的态度

缓存是更新还是删除,对应懒汉式和饱汉式,从处理线程安全实践来讲,删除缓存操作相对难度低一些。如果在删除缓存的前提下满足了查询性能,那么优先选择删除缓存。

更新缓存尽管能够提高查询效率,然后带来的线程并发脏数据处理起来较麻烦,序言引入MQ等其它消息中间件,因此非必要不推荐。

三、线程并发分析

理解线程并发所带来问题的关键是先理解系统中断,操作系统在任务调度时,中断随时都在发生,这是线程数据不一致产生的根源。以4和8线程CPU为例,同一时刻最多处理8个线程,然而操作系统管理的线程远远超过8个,因此线程们以一种看似并行的方式进行。

查询数据

1、非并发环境

在非并发环境中,使用如下方式查询数据并无不妥:先查询缓存,如果缓存数据不存在,查询数据库,更新缓存,返回结果。

public BuOrder getOrder(Long orderId) {    String key = ORDER_KEY_PREFIX + orderId;    BuOrder buOrder = RedisUtils.getObject(key, BuOrder.class);    if (buOrder != null) {        return buOrder;    }    BuOrder order = getById(orderId);    RedisUtils.setObject(key, order, 5, TimeUnit.MINUTES);    return order;}

如果在高并发环境中有一个严重缺陷:当缓存失效时,大量查询请求涌入,瞬间全部打到DB上,轻则数据库连接资源耗尽,用户端响应500错误,重则数据库压力过大服务宕机。

2、并发环境

因此在并发环境中,需要对上述代码进行修改,使用分布式。大量请求涌入时,获得锁的线程有机会访问数据库查询数据,其余线程阻塞。当查询完数据并更新缓存,然后释放锁。等待的线程重新检查缓存,发现能够获取到数据,直接将缓存数据响应。

这里提到分布式锁,那么使用表锁还是行锁呢?使用分布式行锁提高并发量;使用二次检查机制,确保等待获得锁的线程能够快速返回结果

@Overridepublic BuOrder getOrder(Long orderId) {        String key = ORDER_KEY_PREFIX + orderId;    BuOrder order = RedisUtils.getObject(key, BuOrder.class);    if (order != null) {        return order;    }    String orderLock = ORDER_LOCK + orderId;    RLock lock = redissonClient.getLock(orderLock);    if (lock.tryLock()) {        order = RedisUtils.getObject(key, BuOrder.class);        if (order != null) {            LockOptional.ofNullable(lock).ifLocked(RLock::unlock);            return order;        }        BuOrder buOrder = getById(orderId);        RedisUtils.setObject(key, buOrder, 5, TimeUnit.MINUTES);        LockOptional.ofNullable(lock).ifLocked(RLock::unlock);    }    return RedisUtils.getObject(key, BuOrder.class);}

更新数据

1、非并发环境

非并发环境中,如下代码尽管可能会产生数据不一致问题(数据被覆盖)。尽管使用数据库层面乐观锁能够解决数据被覆盖问题,然而无效更新流量依旧会流向数据库。

public Boolean editOrder(BuOrder order) {        updateById(order);        RedisUtils.deleteObject(OrderServiceImpl.ORDER_KEY_PREFIX + order.getOrderId());    return true;}
2、并发环境

上面分析中使用数据库乐观锁能够解决并发更新中数据被覆盖的问题,然而当同一行记录被修改后,版本号发生改变,后续并发流向数据库的请求为无效流量。减小数据库压力的首要策略是将无效流量拦截在数据库之前。

使用分布式锁能够保证并发流量有序访问数据库,考虑到数据库层面已经使用了乐观锁,第二个及以后获得锁的线程操作数据库为无效流量。

线程在获得锁时采用超时退出的策略,等待获得锁的线程超时快速退出,快速响应用户请求,重试更新数据操作。

public Boolean editOrder(BuOrder order) {    String orderLock = ORDER_LOCK + order.getOrderId();    RLock lock = redissonClient.getLock(orderLock);    try {                if (lock.tryLock(1, TimeUnit.SECONDS)) {                        updateById(order);                        RedisUtils.deleteObject(OrderServiceImpl.ORDER_KEY_PREFIX + order.getOrderId());                        LockOptional.ofNullable(lock).ifLocked(RLock::unlock);            return true;        }    } catch (InterruptedException e) {        e.printStackTrace();    }    return false;}

依赖环境

上述代码使用了封装锁的工具类。

<dependency>  <groupId>xin.altitude.cms</groupId>  <artifactId>ucode-cms-common</artifactId>  <version>1.4.3.2</version></dependency>

LockOptional根据锁的状态执行后续操作。

四、先数据库后缓存

数据一致性

1、问题描述

接下来讨论先更新数据库,后删除缓存是否存在并发问题。

(1)缓存刚好失效
(2)请求A查询数据库,得一个旧值
(3)请求B将新值写入数据库
(4)请求B删除缓存
(5)请求A将查到的旧值写入缓存

上述并发问题出现的关键是第5步比第3、4步后发生,由操作系统中断不确定因素可知,此种情况却有发生的可能。

2、解决方式

从实际情况来看,将数据写入Redis远比将数据写入数据库耗时要短,尽管发生的概率较低,但仍会发生。

  • (1)增加缓存过期时间

增加缓存过期时间允许一定时间范围内脏数据存在,直到下一次并发更新出现,可能会出现脏数据。脏数据会周期性存在。

  • (2)更新和查询共用一把行锁

更新和查询共用一把行分布式锁,上述问题不复存在。当读请求获取到锁时,写请求处于阻塞状态(超时会快速失败返回),能够保证步骤5在步骤3之前进行。

  • (3)延迟删除缓存

使用RabbitMQ延迟删除缓存,去除步骤5的影响。使用异步的方式进行,几乎不影响性能。

特殊情况

数据库有事务机制保证操作成功与否;Redis单条指令具有原子性,然后组合起来却不具备原子特征,具体来说是数据库操作成功,然后应用异常挂掉,导致Redis缓存未删除。Redis服务网络连接超时出现此问题。

如果设置有缓存过期时间,那么在缓存尚未过期前,脏数据一直存在。如果未设置过期时间,那么直到下一次修改数据前,脏数据一直存在。(数据库数据已经发生改变,缓存尚未更新)

解决方式

在操作数据库前,向RabbitMQ写入一条延迟删除缓存的消息,然后执行数据库操作,执行缓存删除操作。不管代码层面缓存是否删除成功,MQ删除缓存作为保底操作。

读到这里,这篇“Java并发编程数据库与缓存数据一致性方案是什么”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。

--结束END--

本文标题: Java并发编程数据库与缓存数据一致性方案是什么

本文链接: https://lsjlt.com/news/326283.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java并发编程数据库与缓存数据一致性方案是什么
    本文小编为大家详细介绍“Java并发编程数据库与缓存数据一致性方案是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java并发编程数据库与缓存数据一致性方案是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧...
    99+
    2023-06-29
  • Java并发编程数据库与缓存数据一致性方案解析
    目录一、序言二、不同的声音1、操作的先后顺序2、处理缓存的态度三、线程并发分析查询数据1、非并发环境2、并发环境更新数据1、非并发环境2、并发环境依赖环境四、先数据库后缓存数据一致性...
    99+
    2024-04-02
  • redis系列之数据库与缓存数据一致性解决方案
    场景一 一般来说,只要你用到了缓存,不管是Redis还是memcache,就可能会涉及到数据库缓存与数据的一致性问题,这里我们以Redis为例。 我们该如何保证Redis与数据库的一致性呢?  So easy: 更新的时候,先更新数据库,...
    99+
    2020-08-13
    redis系列之数据库与缓存数据一致性解决方案 数据库入门 数据库基础教程 数据库 mysql
  • 缓存与数据库一致性保证
    全是干货!本文主要讨论这么几个问题:(1)啥时候数据库和缓存中的数据会不一致(2)不一致优化思路(3)如何保证数据库与缓存的一致性一、需求缘起当数据发生变化时,“先淘汰缓存,再修改数据库”这个点是大家讨论的...
    99+
    2024-04-02
  • 保证Redis缓存与数据库一致性的方法是什么
    本文小编为大家详细介绍“保证Redis缓存与数据库一致性的方法是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“保证Redis缓存与数据库一致性的方法是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1、四...
    99+
    2023-07-05
  • PHP开发缓存的数据一致性与并发控制
    PHP开发缓存的数据一致性与并发控制,需要具体代码示例概述:在PHP开发中,缓存是一种常见的技术手段,用于提高数据读取速度和减轻数据库压力。然而,缓存带来了数据一致性和并发控制的挑战,因为在多线程环境中,不同的读写操作可能同时发生。本文将介...
    99+
    2023-11-07
    缓存 PHP开发 数据一致性 关键词:
  • 数据库缓存最终一致性的四种方案分别是什么
    这篇文章将为大家详细讲解有关数据库缓存最终一致性的四种方案分别是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。背景缓存是软件开发中一个非常有用的概念,数...
    99+
    2024-04-02
  • 缓存和数据库一致性问题
    1、想要提高应用的性能,可以引入「缓存」来解决 2、引入缓存后,需要考虑缓存和数据库一致性问题,可选的方案有:「更新数据库 + 更新缓存」、「更新数据库 + 删除缓存」 3、更新数据库 + 更新缓存方案,...
    99+
    2021-04-23
    缓存和数据库一致性问题
  • 怎么保证Redis缓存与数据库的一致性
    这篇文章主要为大家展示了“怎么保证Redis缓存与数据库的一致性”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“怎么保证Redis缓存与数据库的一致性”这篇文章吧...
    99+
    2024-04-02
  • MySQL数据和Redis缓存一致性方案详解
    读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现 缓存(Redis)和数据库(MySQL)间的数据一致性问题。 不管是先写MySQL数据库,再删除Redis...
    99+
    2024-04-02
  • 浅谈数据库缓存最终一致性的四种方案
    背景 缓存是软件开发中一个非常有用的概念,数据库缓存更是在项目中必然会遇到的场景。而缓存一致性的保证,更是在面试中被反复问到,这里进行一下总结,针对不同的要求,选择恰到好处的一致性方...
    99+
    2024-04-02
  • 怎么保证缓存和数据库的数据一致性
    本篇内容主要讲解“怎么保证缓存和数据库的数据一致性”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么保证缓存和数据库的数据一致性”吧!1、错误的解决方案1.1、...
    99+
    2023-04-21
    数据库
  • 怎么保证缓存与数据库的双写一致性
    本篇内容介绍了“怎么保证缓存与数据库的双写一致性”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Cache ...
    99+
    2024-04-02
  • 【分布式】数据库和缓存双写一致性方案解析
    引言为什么写这篇文章?首先,缓存由于其高并发和高性能的特性,已经在项目中被广泛使用。在读取缓存方面,大家没啥疑问,都是按照下图的流程来进行业务操作。但是在更新缓存方面,对于更新完数据库,是更新缓存呢,还是删除缓存。又或者是先删除缓存,再更新...
    99+
    2023-06-02
  • cdn缓存怎么与数据库保持一致
    要将CDN缓存与数据库保持一致,可以采取以下几种方法:1. 缓存更新策略:在数据库中更新数据时,同时触发CDN缓存的更新。可以通过发...
    99+
    2023-09-05
    cdn 数据库
  • 保证缓存和数据库的数据一致性详解
    目录1、错误的解决方案1.1、 先更新数据库,再删除缓存1.2、 先更新数据库,再更新缓存1.3、 先删除缓存,再更新数据库1.4、 先更新缓存,再更新数据库2、正确的解决方案2.1...
    99+
    2023-05-15
    缓存和数据库数据一致性 保证缓存和数据库数据一致性 数据一致性
  • 分布式之数据库和缓存双写一致性方案解析
    先做一个说明,从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案。这种方案下,我们可以对存入缓存的数据设置过期时间,所有的写操作以数据库为准,对缓存操作只是尽最大努力即可。也就是说如果数据库写成功...
    99+
    2024-04-02
  • 详解redis缓存与数据库一致性问题解决
    数据库与缓存读写模式策略 写完数据库后是否需要马上更新缓存还是直接删除缓存? (1)、如果写数据库的值与更新到缓存值是一样的,不需要经过任何的计算,可以马上更新缓存,但是如果对于那...
    99+
    2024-04-02
  • 如何保证缓存与数据库的双写一致性
    本篇内容主要讲解“如何保证缓存与数据库的双写一致性”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何保证缓存与数据库的双写一致性”吧!只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双...
    99+
    2023-06-02
  • 如何保证缓存和数据库一致性
    [TOC] 多年前在一次面试中,被问到如果数据更新,先修改数据库还是先修改缓存。因为没有想过,所以比较懵逼,时候赶紧搜索,发现这里面很有学问。基本上所有的文章最终都指向了两个地方,就是Oracle和Hazelcast对缓存更新策略的介绍。 ...
    99+
    2015-01-22
    如何保证缓存和数据库一致性
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作