DB读写分离情况下,如何解决缓存和数据库不一致性问题?
前言
在读写分离的情况下,缓存和数据库数据不一致怎么解决? 请看这一篇如何更新缓存保证缓存和数据库双写一致性?
如何解决DB数据库的数据不一致问题? 请看这一篇怎么解决DB读写分离,导致数据不一致问题?
在缓存和数据库数据一致性问题中,推荐 先更新数据库,再删除缓存。如果缓存删除失败可以用MQ消息队列的方式进行重试删除。
为什么会导致不一致

上图流程:
1)应用服务(商品服务)请求A更新库存为99,原值为100
2)但主库同步到从库需要时间,还没有同步完成时,请求B发起读请求
3)读请求B走的是从库,取出来从库里面的旧值100
4)读请求B会把取出来的值,再设置到缓存中,值为100
5)但当从库同步数据完成,从库的数据值为99,这就导致数据库和缓存数据不一致
方案一:后台缓存标记法
怎么解决DB读写分离,导致数据不一致问题?里面提到此方案,这边就不重复介绍了,大家可以去那篇文章中查看。
数据不一致问题是因为读请求走的是从库,把从库的旧值又设置到缓存中了。后台缓存标记方案就解决了此问题,在主从数据库同步窗口时间内,读请求也是走主库。这样就解决了读请求取到的是旧值这个问题。
但这个方案也有缺点,就是有系统性能问题,降低了吞吐量
方案二:延迟消息
其实在真实业务中,尤其互联网项目中,数据短时间的不一致时能够接受的。就像怎么解决DB读写分离,导致数据不一致问题?中提到的本地缓存标记法,保证了本用户数据一致,其他用户可暂时不一致,但最终是一致的这个思路。我们可以设置一个延迟消息,如下图

流程:
1)在订阅到binlog更新日志时,先不删除缓存,而是投递一个延迟消息(如:延迟10秒的消息,就是过10秒此消息才会被消费者监听到,从而被消费)
2)延迟消息的延迟时间,设置为主库与从库的数据同步延迟的时间,可自行预估
3)监听到延迟消息,在删除缓存。
这个方案的特点就是读请求会在延迟时间内读取到的是旧值,等到延迟时间一过,取到的就是新值。这个业务在互联网产品中是允许的。
如果要保证本用户(更新数据的用户)一定读到的是新值,这边可以采用本地缓存标记方案,直接从主数据库读取,读取到数据后,可以把新值设置到缓存中,这样就保证了数据一致性。
方案三:更新用户再次发起读请求
在方案二中,其他用户的读请求会有暂时间读取到的是旧值,如何缩短时间?其实是有一个方案,就是让更新用户再次发起读请求,也就是在方案二最后提到的
1)更新用户再次发起读请求,根据本地缓存标记,直接走主数据库,读取的肯定是新值,
2)再把这个新值设置到缓存中。这样就保证了缓存中的是新值,虽然从库还没有不同完成,但缓存中已经是新值了。
3)最后从库同步数据完成,值就达到了一致性
此方案的问题:就是更新操作后,多了一步读请求。
总结:小伙伴可以根据自己的业务需求,选择不同的方案,一定要结合自己的业务,没有什么完美的方案,只是如何取舍而已。
DB读写分离情况下,如何解决缓存和数据库不一致性问题?的更多相关文章
- 阿里云RDS读写分离数据查询延迟解决
mysql使用RDS做数据主从读写分离.在使用的过程中发现部分业务对其他服务以来严重.但是由于系统不是采用微服务的架构,造成部分数据插入数据库后,后续操作读取数据库没有查询到前面插入的数据.查看阿里云 ...
- 如果让你来做HashMap扩容,如何实现在不影响读写的情况下扩容?
我觉得逼格高,不是体现在问题多刁钻,知识点多深,而是一个非常明确,无歧义的问题,能考察出面试者多方面的能力.这个问题背后:1.了解java中,HashMap的实现:如果一个面试者了解这一点,说明至少他 ...
- 基于Mysql-Proxy实现Mysql的主从复制以及读写分离(下)
基于Mysql-Proxy实现Mysql的主从复制以及读写分离(下) 昨天谈到了Mysql实现主从复制,但由于时间原因并未讲有关读写分离的实现,之所以有读写分离,是为了使数据库拥有双机热备功能,至于双 ...
- (转)使用Amoeba 实现MySQL DB 读写分离
Amoeba(变形虫)项目是一个开源框架,于2008年开始发布一款 Amoeba for Mysql软件: 这个软件致力于MySQL的分布式数据库前端代理层,它主要在应用层访问MySQL的时候充当SQ ...
- 使用Amoeba 实现MySQL DB 读写分离
Amoeba(变形虫)项目是一个开源框架,于2008年开始发布一款 Amoeba for Mysql软件: 这个软件致力于MySQL的分布式数据库前端代理层,它主要在应用层访问MySQL的时候充当SQ ...
- Codeigniter开发技巧:连接多个数据库(可实现DB读写分离)
在开发中,我们有时候会遇到在同一程序中链接多个数据库的需求,这对Codeigniter框架来说是很简单的,我们只需要在 database.php文件中配置少许参数即可. 默认情况下,CI配置的是链接一 ...
- Linux开启SELinux的情况下怎么解决nginx403跟502错误
https://www.cnblogs.com/caijt/p/10978324.html 以上篇博客中说了怎么在linux部署asp.net core 跟 nginx,里面成功的前提是把SElin ...
- 使用Spring+MySql实现读写分离(二)spring整合多数据库
紧接着上一章,因为现在做的项目还是以spring为主要的容器管理框架,所以写以下spring如何整合多个数据源. 1. 背景 我们一般应用对数据库而言都是“读多写少”,也就说对数据库读取数据的压力比较 ...
- mysql-unsha1:在未知密码情况下,登录任意MYSQL数据库
摘要 这个POC用于在不知道明文密码的情况下对启用了密码安全认证插件(默认开启插件:mysql_native_password)的MYSQL数据库进行登录. 前提条件为: 1.为了获取到已知用户的ha ...
- 使用Django的时候,页面请求正常,也没有报任何错误,甚至连警告都没有的情况下,页面却还是原地不动或者闪一下或者无限显示加载动画的情况下的解决办法
这个问题描述比较笼统,但根据我目前遇到过两种情况来看,似乎都比较重要而且实用,所以打算分别讲述一下. 说明:Django的版本是Django2.0 第一种:URL配置错误 页面闪一下,却原地不动,可能 ...
随机推荐
- Qt音视频开发3-vlc录像存储
一.前言 录像功能是视频监控系统的常用功能,就是将打开的视频流或者视频文件重新保存成MP4文件,当然也可以保存成其他格式,一般默认用MP4比较好,比较标准一些,MP4格式的兼容性最好,基本上没有说那台 ...
- 从异常{ 无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型 }说开去
从异常{ 无法将 匿名方法 转换为类型"System.Delegate",因为它不是委托类型 }说开去. 查看如下代码: this.Invoke(delegate { Messag ...
- [LC593]有效的正方形-Valid Square
题目描述 给定2D空间中四个点的坐标 p1, p2, p3 和 p4,如果这四个点构成一个正方形,则返回 true . 点的坐标 pi 表示为 [xi, yi] .输入 不是 按任何顺序给出的. 一个 ...
- 前端学习openLayers配合vue3(简单的创建一个地图)
首先搭建一个vue工程化环境,首先我们先来创建一个地图吧 首先我们需要下载 npm i ol 其次我们需要在main.js里面引入相关的css import 'ol/ol.css' 到现在我们就可以开 ...
- Docker安装Redis并设置密码
1. 镜像下载 docker pull redis 2. 创建目录 mkdir -p /etc/redis/redis.conf mkdir -p /data/redis 3. 启动容器 docker ...
- sshd 启动失败
解决方法 yum remove openssh yum install openssh openssh-server openssh-clients systemctl start sshd syst ...
- CDS标准视图:有技术对象的维修工单 I_MAINTORDERTECHOBJCUBE
视图名称:有技术对象的维修工单 I_MAINTORDERTECHOBJCUBE 视图类型:基础 视图代码: 点击查看代码 @EndUserText.label: 'Maintenance Order ...
- JAVA调用groovy脚本的方式
一.使用用 Groovy 的 GroovyClassLoader ,它会动态地加载一个脚本并执行它.GroovyClassLoader是一个Groovy定制的类装载器,负责解析加载Java类中用到的G ...
- Nginx日常运维方法Linux版
1,安装? 下载RPM:wget http://nginx.org/packages/centos/7/x86_64/RPMS/nginx-1.10.0-1.el7.ngx.x86_64.rpm 离线 ...
- openbox每日开机自动切换网络壁纸
目的 利用bing的每日一图, 每天切换壁纸 开干 联网后下载图片 利用networkmanage启动后执行脚本 netafter.sh 文件地址: /etc/NetworkManager/dispa ...