当前位置:   article > 正文

面试总结-如何保证redis和mysql的数据一致性_先更新数据库,再删除缓存,使用mysql binlog日志

先更新数据库,再删除缓存,使用mysql binlog日志

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文件中的日志,并解析成具体操作,通过主从的操作一致,而达到最终数据一致

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/368001
推荐阅读
相关标签
  

闽ICP备14008679号