如何保证Redis和MySQL数据一致性,这个问题真的是面试问的最多的一个问题了,所以总结一下,类似的问题,比如如何保证ES和MySQL的数据一致性,凡是涉及到数据多个地方读写,有数据一致性的需求和同步操作,以下总结的方法都可考虑。
什么是数据一致性
Redis和MySQL数据一致性说的是,Redis作为缓存,必须保持跟MySQL中数据一致,在更新MySQL数据的时候,Redis中也必须更新到最新的值,这样先从Redis缓存中读取的值就是我们最新的值,不会有脏数据。
如何保持数据一致性
核心:保证更新缓存的操作能够按照数据库数据的更新串行执行,不会发生旧数据覆盖新数据。
-
强一致性
思路:
订阅消费mysql master节点的binllog,消费修改、删除的binlog语句,binlog就相当于一个顺序队列,能够保证对数据操作的顺序性,只要在数据库事务完成,提交写入binlog日志后, 根据binlog日志顺序更新缓存(注意,不是删除,直接更新缓存为最新数据),可以保证数据的强一致性。实现:
比较火的就是用阿里开源的canal组件,搭建一个专门的模块服务去订阅消费binlog。优点
能够实时的保证Redis和MySQL中数据的一致性缺点
引入额外的系统模块,增加复杂度。 -
弱一致性(最终一致性)
思路:
先删除缓存,再更新数据库,缓存要设置过期时间。实现:
先删除缓存,再更新数据库。更好一点的,延时双删,即先删除缓存,再修改数据库,再删除缓存,这种情况也会存在数据一致性问题。
1)先删除缓存; 2)再写数据库; 3)休眠500毫秒(根据具体的业务时间来定,休眠是为了最大程度上避免脏数据的写入) 4)再次删除缓存。
优点
无开发难度缺点
在高并发情况下,会出现数据不一致性,但是过期时间保证了脏数据只会存在一定的时间,在过期之后,会从数据库获取最新的数据。
总结
缓存一般只是解决读性能低下的问题,更新数据库和更新缓存是两个操作,不仅要保证这个操作的原子性,还要保证更新缓存的顺序问题,要保证对缓存的更新必须能够按照数据库数据更新的顺序来执行,但是,在更新缓存的时候,可能会因为网络延迟等问题,
先执行的更新操作慢于后执行的更新操作,就会覆盖掉新数据,产生脏数据。在一定要保证获取最新数据的场景下,建议放弃使用缓存,从数据库读取最新的数据。如果可以接收数据最终一致性,那就采用先删除缓存再更新数据库的策略。