在增删改数据后,我们往往需要删除旧缓存,以生成新的缓存,但是redis和mysql无论谁先执行都不能保障另一个会失败,所以会出现不一致问题。
首先需要确定的是,由于网络等各种原因的限制,mysql与redis数据是不可能保持强一致性的,就算是单机、mysql加锁、串行化执行都不能保证强一致性。通常我们所说的一致性需要根据业务场景综合分析对策。
个人认为一致性的要求分为“时效性”和“准确性”两方面。
时效性:mysql更新后redis尽快删除。
准确性:mysql更新后redis也要删除,尽可能减少更新的丢失。
普通缓存
时效性和准确性要求都并不高,即使某次redis删除失败也没大的影响,无需特殊处理,要求较高时可以适当缩短缓存时长。
热点key、更新极少的key
时效性要求可以稍微低一点,但是准确性要求较高,可以获取redis删除结果,删除失败可以放入MQ。
删除成功并不能保障真的成功,因为redis异步确认的特点,有可能是在故障转移期间先答复客户端成功但实际没成功。
通常热点key能接受这种概率,如果不能就需要像内存数据库这样加上定时任务去增量和全量比对redis和mysql。
内存数据库
如果是读多而写特别少的场景,缓存时长通常更长,甚至写过一次就长期有效作为内存数据库使用或者作为系统设置,此时缓存准确性要求会很高。
数据库日志分析+MQ
通过binlog工具如canal等监测mysql的binlog,再把监测到的更新通过MQ推送到redis服务器进行消费,实时性较高,且MQ大都支持重投、重试等,可以保障redis最终能和mysql保持一致。
Canal的部署支持集群,需要配合ZooKeeper进行集群管理。
参考:
https://blog.youkuaiyun.com/yehongzhi1994/article/details/107880162
https://blog.youkuaiyun.com/yehongzhi1994/article/details/108034330
异步线程更新
一种开销比较小的方式是,定时比如每五分钟对指定数据表五分钟内的数据进行扫描,和redis中数据进行对照,每天凌晨在redis中对前一天mysql的更新进行检查,这种更适合redis做内存数据库并且可以容忍一段时间内数据不一致的情况。
直观展示
如后台设置,需要用到redis时可以直接查看mysql、redis的值,一旦真的不一样可以手动修改。
在数据库更新后,如何确保Redis缓存的一致性是一大挑战。文章讨论了不同一致性要求下的解决方案,包括普通缓存、热点key的处理、内存数据库场景以及利用MySQL binlog和MQ实现最终一致性。同时,提出了异步线程更新和后台检查的方法来降低数据不一致的影响。
1万+

被折叠的 条评论
为什么被折叠?



