Redis面经——Redis的双写一致性,一篇文章带你彻底搞懂什么是Redis的双写一致,如何推演实现的?以及成熟的解决方案!黄金文档!

一、双写一致性概念
当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致

Redis的双写一致性,一般是基于两种场景,第一个是追求强一致性,第二个允许延迟一致(保证数据的最终一致性)

二、保证双写一致性细节

追求强一致性

(一)读操作
缓存命中,直接返回;缓存没有命中则查询数据库,写入缓存,设定超时时间

(二)写操作
延迟双删

那么问题来了,是先删除缓存呢还是先修改数据库呢?
1、先删除缓存,再操作数据库
假设最开始缓存和数据库中的数据都是10条

有两个线程
(1)先删除缓存

(2)更新数据库数据

(3)查询缓存,缓存未命中,则查询数据库,将数据写入到缓存中

但是这种方式还是会存在问题的!
请继续往下看
(1)线程1此时删除了缓存,由于线程的调度完全是由CPU来控制,此时线程1挂起,而线程2开始查询数据,此时线程2肯定是未命中的状态,就去查询数据库,并将数据库更新前的数据又重新写入到缓存了

(2)此时,线程1开始执行,线程1完成了数据库的数据更新,数据库数据变成了20,但是此时的缓存中数据还是10,这就造成了脏数据的情况!!!

2、先操作数据库,再删除缓存
1)正常的流程
假设初始缓存和数据库中的数据都是10

线程2开启,并直接更新了数据库,然后线程2删除了缓存。此时线程1查询缓存,发现缓存未命中,直接去查询数据库,此时查询的数据是正确的,然后紧接着将数据库更新后的数据写到缓存中了。到此为止,数据还是一致性的


2)存在的问题
(1)如果此时缓存中的数据过期了,那么线程1是拿不到数据的,直接查询数据库拿到一开始的10

(2)接下来线程2在线程1未同步到缓存前,先更新数据库,并且删除了缓存(此时缓存中key已经过期,删不删除都是一样的),线程2成功将数据更新成了20,但是线程1开始执行,将一开始读取到的10写入到了缓存中,又总成了数据的不一致!

我们继续回到上面的问题
写操作,要延迟双删

那么又有一个新的问题,就是为什么要删除两次缓存呢?
因为再次删除缓存,目的就是为了降低脏数据的风险

还又一个新的问题,为什么要延时删除呢?
因为数据库一般都是搭建主从集群的,所以要等待数据库的数据全部同步后开始删除缓存,否则还是会出现脏数据的情况。注意,这种方式没有绝对的一致性,延时多久不可预知,如果出现主从未完全同步时写入缓存,还是会导致脏数据

保证写操作强一致性的方法!!!!重头戏!!!!!!
1、加入分布式锁,来控制

2、进阶版
因为一般写入到缓存中的数据都是读多写少的情况,这个时候我们就不用分布式锁了,直接使用读写锁!

具体的代码实现:
下面的读写代码,一定可以实现强一致性!但是性能就很低了!

(1)读操作:

(2)写操作:
注意读写锁的锁要保持一致

允许延迟一致(保证数据的最终一致性)

1、异步通知来保证数据的最终一致性

2、基于Canal的异步通知
canal是基于MySQL的主从同步来实现的
会监听主节点的binlog文件,binlog二进制文件中记录了所有的DDLH和DML语句,但是不包括数据查询,比如select或者show语句。
当文件发生更新了,那么就会通知缓存数据变更的情况。这种方式是对业务代码0侵入的,如果我们的业务场景中允许数据短暂延时,这种方式还是相对推荐的

至此,关于双写一致性的推演介绍完毕,内容比较多,希望大家能够收藏反复学习,后续还会持续更新相关面试题,敬请期待!!!

在微服务架构中,保障数据一致性是核心挑战之一,尤其是当涉及到多个服务共享数据源,如Redis和MySQL时。为了深入理解这个问题,建议您查阅《20届大厂社招经:字节、阿里、虾皮、滴滴技术挑战与经验分享》这份资料,它详细记录了技术试官在数据一致性问题上的深入提问。 参考资源链接:[20届大厂社招经:字节、阿里、虾皮、滴滴技术挑战与经验分享](https://wenku.csdn.net/doc/36ak2xexrm) 在实现数据一致性保障时,首先需要明确不同场景下的需求和选择合适的一致性级别。例如,在使用Redis缓存时,可能会接受最终一致性,而在MySQL数据库中,则可能需要保证强一致性。 具体到Redis和MySQL的数据一致性,可以采取以下几种策略: 1. 一致性策略:在更新数据时同时更新Redis和MySQL。这要求使用事务确保两者更新的原子性,或者通过消息队列异步更新Redis,但要注意处理消息队列中的消息重复问题。 2. 读分离策略:在读取数据时,首先尝试从Redis中读取,若不存在,则从MySQL中读取并回Redis。这需要在缓存逻辑中增加缓存穿透的防护措施,如布隆过滤器,以及处理缓存失效时的数据一致性问题。 3. 删除策略:在数据删除时,应当从MySQL和Redis中同时删除,以避免无效数据的存在。在分布式系统中,这通常涉及到分布式锁或者基于消息的最终一致性机制。 4. 延时删策略:在某些场景下,可以先删除缓存,然后再更新数据库,最后在一定延时后再次删除缓存,以减少缓存一致的情况发生。 在实际项目中,还可以结合使用消息队列、事件总线等技术来提高数据一致性的保障能力。例如,使用RabbitMQ、Kafka等消息中间件来确保数据更新操作的顺序性和可靠性。 最终,实现微服务架构下Redis和MySQL的数据一致性需要结合具体的业务场景和需求,以及系统的设计目标来选择合适的技术和策略。通过深入理解这些技术原理和实践案例,可以为您的技术试和实际工作提供有力支撑。 参考资源链接:[20届大厂社招经:字节、阿里、虾皮、滴滴技术挑战与经验分享](https://wenku.csdn.net/doc/36ak2xexrm)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Be explorer

若认可笔者文章,手头富裕望支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值