面试总结-如何保证redis和mysql的数据一致性

文章讨论了在更新数据库和缓存时可能出现的四种不推荐方案,包括并发读写不一致性和脏数据问题。提出了延迟双删策略及其优化,以及使用canal订阅binlog实现最终一致性。强调在追求性能提升的同时,应权衡一致性需求,通常目标是达到最终一致性而非强一致性,并介绍了MySQL的主从复制原理。
摘要由CSDN通过智能技术生成

1. 不推荐的四种方案

1.1. 先更新数据库,再更新缓存

1.2. 先更新缓存,再更新数据库

以上两种情况存在多线程并发双写不一致性

1.3. 先删除缓存,再更新数据库(优化方案,延迟双删方案)

T1删缓存;T2读缓存未命中,后读数据库,再更新缓存;T1再更新数据库;T3再读缓存(脏数据)

1.4.先更新数据库,再删除缓(优化方案,canal订阅binlog日志方案)

T1读缓存未命中,再查询数据库;T2更新数据库,再删缓存;T1更新缓存;T3再读缓存(脏数据)

以上两种情况存在多线程并发读写不一致性存

2. 延迟双删(最终一致性)

A. T1删除缓存,再更新数据库;

B. T2(或多个线程)在T1更新完之前读取数据库旧数据,再写入缓存;

C. T1更新完数据库,再睡眠n秒(具体看T2的数据业务逻辑时间),待T2读写结束,再次删除缓存;

D. T3查询缓存未命中,再查询数据库最新该数据(是T1更新的数据)。保证了mysql和redis的一致性

2.1延迟双删存在的问题:

A. 睡眠延迟时间不好确定(T1线程sleep的时间, 需要大于T2线程读取数据再写入Redis缓存的时间.)

B. mysql若是读写分离架构,线程睡眠时间还需要加上从机自主机同步数据的时间

C. 睡眠延迟导致吞吐量降低

D. T2在第二次删除缓存时,删除缓存失败

2.2优化延迟双删方案:

T2延迟后第二次删除缓存,但若删除失败,也导致数据库和缓存的数据不一致

因此提出优化解决方案,删除失败的缓存,进入mq消息队列,实现异步重试删除,直至删除成功。若重试达到次数上限还未成功,直接报错或发通知,再手动处理,保证最终一致性

优化后的缺点:业务代码被入侵

3. 同canal订阅binlog日志(最终一致性)

3.1. 先更新数据库

3.2. 数据库将操作sql信息写入binlog

3.3. 通过canal订阅binlog,并提取所需数据及key

3.4. 另起业务代码,获取canal的订阅数据,解析目标key

3.5. 尝试删除这些key的缓存,若删除失败,将这些删除失败的数据推至mq

3.6. mq再通过异步重试,执行删除操作

canal是阿里出的一个增量数据同步工具,原理就是伪装成mysql Slave向master发送jdump协议,master收到dumpq请求,开始推送binlog给canal,然后canal解析binlog中的sql,发往存储目的地,如mysql、kafka、es、mq、redis等

4. 若要实现mysql和redis的强一致性,怎么办?

一致性协议方案:2PC、Paxos一致性算法、分布式锁等;这些方案往往比较复杂,影响系统性能

但是我们引入redis缓存的目的是什么?是提升系统性能,比如我们可以通过加分布式锁的方式来实现强一致性,但我们也要付出相应的代价,甚至很可能会超过引入缓存带来的性能提升。因此没必要追求强一致性,只能尽可能地去降低出现数据不一致的概率,并达到最终一致性。

同时设置redis缓存失效时间,虽然会有短时间数据不一致,但失效时间兜底也能保证最终一致性

5. mysql的主从复制原理

1. 开启binlog日志,mysql安装目录下的my.ini配置文件,添加一句log_bin = mysql_bin即可

2. mysql会把所有的DDL、DML、TCL写入BinaryLog日志文件中

3. Master会开启一个 log dump 线程,用来给从库的 i/o线程传binlog

4. 从库的i/o线程去请求主库的binlog,并将得到的binlog日志写到中继日志(relaylog)中

5. 从库的sql线程,会读取relaylog文件中的日志,并解析成具体操作,通过主从的操作一致,而达到最终数据一致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值