Redis与Mysql的数据一致性

如果要修改一个Redis和mysql共存的数据,在Redis中我们到底是修改数据,还是删除原有数据再添加新的数据呢?还有我们到底是先操作Redis缓存还是先操作数据库呢?这些都是和数据的一致性来挂钩的。

因为更新缓存的成本很高,所以我们在Redis中选择先删除、后添加的方式。

1.先操作Redis缓存(先删后更新)

正常的过程就是当数据修改时,先删除Redis中的缓存数据,之后再更新mysql数据库,然后后面的线程如果要查询数据,在Redis中查询不到,就会去mysql中查询并放入缓存中。但是如果网络延迟数据库没有及时更新,这样可能会导致后面的线程始终访问的都是脏数据,如下情况:

Redis与Mysql的数据一致性_第1张图片 

网络延迟问题的解决方式就是使用延迟双删,就是当数据库数据进行更新之后,如果Redis缓存了旧数据,再对Redis中的数据进行一次延迟删除,延迟的目的就是防止这次延迟删除刚好进行在其他线程将旧数据放到缓存的前面,这样我们就保证了最终一致性

强一致型的实现需要加锁,但是这样会大大降低吞吐量,所以不采取。

2.(推荐)先操作数据库(先更新后删)

正常的情况是当数据发生修改时,我们先修改mysql数据库,修改完数据库后再删除Redis中的缓存。但是如果在删除Redis缓存前,其他的线程来访问时,都是访问Redis中的脏数据,等到删除Redis中的脏数据时,才会到数据库中查询最新的数据,这样在正常的情况下会保证最终一致性。但是如果极端的情况下,如果删除缓存时出错(延迟双删可能存在此问题),就会出现问题:

Redis与Mysql的数据一致性_第2张图片

3.删除缓存时出错问题解决方法

解决方法就是删除重试机制,引入消息队列,如果Redis那边删除失败,通过异步发送信息到MQ,然后线程那边监听到MQ中的消息,重试删除即可,但是采用这种方式会导致业务代码的耦合度比较高,优化的策略是使用Cannal监听mysql中binlog日志的变化,如果有变化,则通知Cannal客户端(可以为springboot)去负责删除Redis中的缓存,如果中途删除有问题,也会发送异步信息到MQ中,Cannal客户端去监听MQ。

Redis与Mysql的数据一致性_第3张图片 

 

你可能感兴趣的:(Redis,mysql,redis,mysql,数据库)