如今在Web系统中,缓存的应用是保证系统吞吐量必不可少的技术。好多开发者认为,缓存太简单啦,一顿set和get操作就完事了,真的是很So easy!听到这些话,我笑了~~
我为什么笑呢,有缓存使用经验的老铁们可能会明白,系统缓存和数据库数据一致性问题一直是技术界讨论的话题,现在我们就讨论下,系统和数据库如何才能保证数据一致性呢?
首先大家要明白不使用更新缓存,而是使用删除缓存策略这句话,这里不做原因赘述,不理解的铁子可以自行百度。
我们先研究下是先删除缓存然后操作数据库还是先操作数据库再删除缓存:
一、先删除缓存,再更新数据库策略
该策略会导致数据的不一致性,场景如下:
1、用户张三进行了数据库写操作,删除缓存
2、同时用户李四进行了查询操作,此时缓存已被删除,去数据库查询得到旧值写入缓存
3、用户张三新数据成功写入数据库
这种情景下发生了缓存和数据库数据的不一致,如果缓存没有设置过期时间,那么该数据永远是脏数据,不一致性将会一直持续下去。
二、先更新数据库、再删除缓存
该策略同样会导致数据的不一致性,场景如下:
场景1:系统在没有做删除缓存失败重试机制的前提下,更新数据库成功,删除缓存失败导致数据不一致
场景2:(1)此时缓存刚好失效
(2)张三发送请求查询数据库,得到旧值
(3)李四发送请求向数据库写入数据,然后删除缓存
(4)此时张三将查询的旧值写入缓存
以上场景均会导致严重的后果,那我们如何解决呢?
先删除缓存,再更新数据库策略解决方案(延迟双删)
1、先删除缓存
2、在写数据库
3、休眠一段时间(例如200ms或1秒,这样根据系统具体情况而定),再次删除缓存(此次操作最好做异步处理)
先更新数据库、再删除缓存策略解决方案
同样采用延迟双删方法即可解决
那么问题又来了,如何删除缓存失败怎么办?
技术大佬们会不假思索的说采用重试机制呗,那下面我们就来说说重试机制。
方案一:1、更新数据库数据
2、删除缓存,但由于某些因素删除失败
3、将删除失败缓存的key发送到消息队列(例如:RabbitMQ、kafka等)
4、自己消费消息、获得key,执行删除操作
方案二:(还在探索中)
技术采坑不容易,若有错误,欢迎指正!