redis和数据库数据一致性问题 - 编程思维

 在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节。所以,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问Mysql等数据库。这样可以大大缓解数据库的压力。具体业务流程如下:

        读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存和数据库间的数据一致性问题。不管是先写数据库,再删除缓存;还是先删除缓存,再写库,都有可能出现数据不一致的情况。举个例子:

        1.如果删除了缓存Redis,还没有来得及写库MySQL,另一个线程就来读取,发现缓存为空,则去数据库中读取数据写入缓存,此时缓存中为脏数据。

        2.如果先写了库,在删除缓存前,写库的线程宕机了,没有删除掉缓存,则也会出现数据不一致情况。

        因为写和读是并发的,没法保证顺序,就会出现缓存和数据库的数据不一致的问题。如何解决?这里给出两个解决方案,先易后难,结合业务和技术代价选择使用。

一、 延时双删策略
        在写库前后都进行redis.del(key)操作,并且设定合理的超时时间。具体步骤是:

        1)先删除缓存

        2)再写数据库

        3)休眠500毫秒(根据具体的业务时间来定)

        4)再次删除缓存。

        那么,这个500毫秒怎么确定的,具体该休眠多久呢?

        需要评估自己的项目的读数据业务逻辑的耗时。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。

        当然,这种策略还要考虑 redis 和数据库主从同步的耗时。最后的写数据的休眠时间:则在读数据业务逻辑的耗时的基础上,加上几百ms即可。比如:休眠1秒。

二、设置缓存的过期时间
        从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案。所有的写操作以数据库为准,只要到达缓存过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存

        结合双删策略+缓存超时设置,这样最差的情况就是在超时时间内数据存在不一致,而且又增加了写请求的耗时。

三、如何写完数据库后,再次删除缓存成功?
        上述的方案有一个缺点,那就是操作完数据库后,由于种种原因删除缓存失败,这时,可能就会出现数据不一致的情况。这里,我们需要提供一个保障重试的方案。

1、方案一具体流程
        (1)更新数据库数据; 

        (2)缓存因为种种问题删除失败;

        (3)将需要删除的key发送至消息队列;

        (4)自己消费消息,获得需要删除的key;

        (5)继续重试删除操作,直到成功。

        然而,该方案有一个缺点,对业务线代码造成大量的侵入。于是有了方案二,在方案二中,启动一个订阅程序去订阅数据库的binlog,获得需要操作的数据。在应用程序中,另起一段程序,获得这个订阅程序传来的信息,进行删除缓存操作。 

2、方案二具体流程
        (1)更新数据库数据;

        (2)数据库会将操作信息写入binlog日志当中;

        (3)订阅程序提取出所需要的数据以及key; 

        (4)另起一段非业务代码,获得该信息;

        (5)尝试删除缓存操作,发现删除失败; 

        (6)将这些信息发送至消息队列;

        (7)重新从消息队列中获得该数据,重试操作。

版权声明:本文版权归作者所有,遵循 CC 4.0 BY-SA 许可协议, 转载请注明原文链接
https://segmentfault.com/a/1190000041417187

.net core下分表分库解决方案--多租户 - 编程思维

介绍本期主角:ShardingCore 一款ef-core下高性能、轻量级针对分表分库读写分离的解决方案,具有零依赖、零学习成本、零业务代码入侵dotnet下唯一一款全自动分表,多字段分表框架,拥有高性能,零依赖、零学习成本、零业务代码入侵,并且支持读写分离动态分表分库,同一种路由可以完全自定义的新星组件,通过本框架

深入浅出特征工程 – 基于 openmldb 的实践指南(上) - 编程思维

1. 什么是机器学习的特征工程一个真实场景的机器学习应用一般会包含两个主体流程,即特征工程和机器学习模型(以下简称模型)。大家对模型一定很了解,平时也是接触的最多的,比如从经典的逻辑回归、决策树模型,到近几年大火的深度学习模型,都是聚焦于如何开发高质量的模型。对于特征工程,可能大家相对关注较少。但是大家一定听说过坊间传

mysql安装教程 - 编程思维

安装环境:windows10 专业版在卡法的过程中,我们大部分会使用到数据库,本次介绍mysql数据库的安装教程!从官网下载社区版服务器压缩包 https://dev.mysql.com/downloads/mysql/ 在解压出的目录下新建my.ini文件,配置如下: [mysqld] # 设置3306端口 port

mysql 索引 - 编程思维

索引索引本质是一种数据结构,目的是为了提高数据查询的效率,尽可能减少 IO 次数。大大减少服务器需要扫描的数据量帮助服务器减少排序过程和避免生成临时表可以把 随机 IO 转变为 顺序 IO有效使用索引会大大提升查询效率,但会增加磁盘空间和降低插入效率常见的索引类型哈希索引哈希索引(Hash Index)是基于哈希表实现

mysql 表结构 - 编程思维

表结构本文总结自《MySQL技术内幕:InnoDB存储引擎(第2版)》索引组织表InnoDB 存储引擎中,表都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(Index organized table)InnoDB 存储引擎表中,每张表都有主键,如果创建表时没有显式定义主键,则会按照以下规则创建:如果表中有非

事务的acid特性_真正的飞鱼-编程思维

事务机制 · 语雀 (yuque.com) 介绍事务 技术是为了解决问题而生的,通过事务我们可以解决以下问题: 多个操作不是一个整体操作,出现了部分执行成功的情况,导致数据的状态不一致问题(原子性) 一组操作只有部分完成,没有全部完成,但是此时可以访问到数据的不一致状态问题(可见性问题,隔离性) 两组操作并发执行,导

mysql全面瓦解14:事务_hello-brand-编程思维

关于事务 我们在数据库中需要执行一个系列的操作的时候,要保证这个系列执行的连续性和完整性,要么整个系列的执行都成功,要么就全部失败(只要有一个步骤失败,其他均回滚到之前的状态), 保证不会存在一部分成功一部分失败的情况。这就是我们事务的职责。下面举个分苹果的例子: A同学有3个苹果,B同学有2个苹果,如果A同学给一个苹

分布式初探——讲透分布式系统一致性模型_coder梁-编程思维

本文始发于个人公众号:TechFlow 在计算机系统的领域,一致性可以说是一个高频词,可能出现的场景很多。从分布式系统到数据库的事务,都有它的身影。 之前我们在介绍数据库事务的时候,谈到过事务的一致性。在数据库当中,一致性是一种目的,不是一种手段。数据库希望控制事务的原子性、隔离性和持久性来保证数据的一致性。这里的一致

面试题:如何保证缓存与数据库的双写一致性? - 编程思维

前言 只要用缓存,就可能会涉及到缓存与数据库双存储双写。 你只要是双写,就一定会有数据一致性的问题。 那么你如何解决一致性问题? 面试题剖析 一般来说,如果允许缓存可以稍微的跟数据库偶尔有不一致的情况,也就是说如果你的系统不是严格要求 “缓存+数据库” 必须保持一致性的话,最好不要做这个方案,即:读请求和写请求串行化,

译|eventually consistent - 编程思维

一年前,我写过一致性模型的文章的第一个版本。因为当时写的很匆忙,而且这个主题非常重要,值得更缜密的对待,所以我并不是很满意。ACM Queue 为将其发布到自己觉得杂志上,所以请我仔细推敲。我得以借此机会改进这篇文章。本文就是最新的版本。最终一致性 - 在全球范围内构建可靠的分布式系统需要在一致性和可用性之间进行权衡。

一文搞定缓存和数据库一致性 - 编程思维

引言在如今的系统开发中,为了提高业务和接口的处理速度,缓存数据已经变成开发模式的常规操作。通过引入缓存减少数据库的查询操作,提高数据的查询速度。但任何一件事情都要从它的两个面去看。引入缓存在带来诸多优势的同时,也相应的提高了系统的复杂性,比如:如何保证缓存和数据库的一致性。缓存策略在实际业务中,我们经常采用的一种缓存策