数据库和缓存一致性问题

hello,各位小伙伴们大家好,我是颜书凌,下面给大家讲解一下数据库和缓存的一致性问题,话不多说

1、一致性介绍

一致性就是数据保持一致,在分布式系统中,可以理解为多个节点中数据的值是一致的。

  • 强一致性:这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验好,但实现起来往往对系统的性能影响大
  • 弱一致性:这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值,也不承诺多久之后数据能够达到一致,但会尽可能地保证到某个时间级别(比如秒级别)后,数据能够达到一致状态
  • 最终一致性:最终一致性是弱一致性的一个特例,系统会保证在一定时间内,能够达到一个数据一致的状态。这里之所以将最终一致性单独提出来,是因为它是弱一致性中非常推崇的一种一致性模型,也是业界在大型分布式系统的数据一致性上比较推崇的模型。

2、问题来源

使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问MySQL等数据库:

读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)之间的数据一致性问题。

不管是先写MySQL数据库,再删除Redis缓存;还是先删除缓存,再写数据库,都有可能出现数据不一致的情况。

3、举例说明

我这里举两个个例子:

1、先更新MySQL,再更新Redis

如果更新Redis失败,可能仍然不一致

2、先删除Redis缓存数据,再更新MySQL

再次查询的时候再将数据添加到缓存中,这种方案能解决1方案的问题,但是在高并发的场景下,性能较低,而且仍然会出现数据不一致的问题,比如线程1删除了Redis缓存数据,正在更新MySQL,此时另外一个查询再次请求,那么就会把MySQL中的老数据又同步到Redis中。

原因:因为读和写实并发的,没法保证顺序,就会出现缓存和数据库的数据不一致的问题

4、解决方案

a. 延迟双删

    先删除Redis缓存数据,再更新MySQL,延迟几百毫秒再删除Redis缓存数据,这样就算再更新MySQL时,有其他线程读了MySQL,把老数据读到了Redis中,那么也会被删除掉,从而把数据保持一致。

出现的问题:延迟双删,所延迟的时间非常的难以确定,所以并不推荐延迟双删。即使先修改数据库,在删除缓存,还是有一定的时间会导致读取到旧数据。还有如reids删除失败等一系列问题

b.队列+重试机制

       

步骤:

更新数据库数据

缓存因为某种原因或者问题删除失败

将需要删除的key发送至消息队列

自己消费消息,获取需要删除的key

继续重试删除操作,直到成功

缺陷:虽然保证了数据的最终一致性,但是会对业务线的代码造成大量的侵入。

c.异步更新缓存(基于订阅binlog的同步机制)

       

MySQL中产生了新的写入、更新、删除等操作,就可以把binlog相关的消息推送至Redis,Redis再根据binlog中的记录,对Redis进行更新。

其实这种机制,很类似MySQL的主从备份机制,因为MySQL的主从备份也是通过binlog来实现的数据一致性

5、实际应用

使用阿里的一款开源框架canal,通过该框架可以对MySQL的binlog日志进行监控,而canal正是模仿了mysql的slave数据库的备份请求,使的Redis的数据更新达到了相同的效果,MQ的消息中间件可以采用rabbitMQ来实现推送

本篇文章到此就结束啦,希望对你有所帮助

  • 35
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值