赞
踩
1.1. 先更新数据库,再更新缓存
1.2. 先更新缓存,再更新数据库
以上两种情况存在多线程并发双写不一致性
1.3. 先删除缓存,再更新数据库(优化方案,延迟双删方案)
T1删缓存;T2读缓存未命中,后读数据库,再更新缓存;T1再更新数据库;T3再读缓存(脏数据)
1.4.先更新数据库,再删除缓(优化方案,canal订阅binlog日志方案)
T1读缓存未命中,再查询数据库;T2更新数据库,再删缓存;T1更新缓存;T3再读缓存(脏数据)
以上两种情况存在多线程并发读写不一致性存
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.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等
一致性协议方案:2PC、Paxos一致性算法、分布式锁等;这些方案往往比较复杂,影响系统性能
但是我们引入redis缓存的目的是什么?是提升系统性能,比如我们可以通过加分布式锁的方式来实现强一致性,但我们也要付出相应的代价,甚至很可能会超过引入缓存带来的性能提升。因此没必要追求强一致性,只能尽可能地去降低出现数据不一致的概率,并达到最终一致性。
同时设置redis缓存失效时间,虽然会有短时间数据不一致,但失效时间兜底也能保证最终一致性
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文件中的日志,并解析成具体操作,通过主从的操作一致,而达到最终数据一致
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。