针对这两点问题,一共可以分为四种方案:
1、先更新缓存,再更新数据库;
2、先更新数据库,再更新缓存;
3、先淘汰缓存,再更新数据库;
4、先更新数据库,再淘汰缓存。
更新缓存、淘汰缓存的优缺点:
淘汰缓存
优点:操作简单,不用关心更新操作,直接将缓存中的旧值淘汰
缺点:淘汰缓存后,下一次查询无法命中缓存,需要重新读取数据库,业务复杂或者数据量大时,响应慢
更新缓存
优点:命中率高,简单key-value更新缓存和淘汰缓存效率差不多
缺点:更新缓存消耗较大。当更新操作简单,如只是将某个值直接修改时,更新缓存和淘汰缓存的消耗查不多;但当更新操作逻辑较复杂时,需要涉及到其他数据或者计算、比较才能得到最终结果,此时更新缓存的消耗要大于直接淘汰缓存。
所以实践中我一般是 简单key-value 可以依据个人习惯采用更新缓存或淘汰缓存都可以,复杂的key-value一般采用淘汰缓存机制。
单机情况下淘汰缓存和更新数据库顺序如何选择?哪种对业务的影响最小?
1、先淘汰缓存,后更新数据库
如果第一步先淘汰缓存成功,第二步更新数据库失败,此时再次查询缓存无法命中缓存,会重新查询数据库。
2、先更新数据库,在淘汰缓存
如果第一步更新数据库成功,第二步淘汰缓存失败,则会导致数据库中是最新的,缓存是旧的,导致数据不一致。
解决办法:为确保缓存删除成功,需要增加“重试机制”逻辑,直到缓存删除成功
单机情况下,采用 先淘汰缓存,后更新数据库(更新失败需要重试机制)或者先更新数据库,在淘汰缓存(淘汰缓存失败需要增加重试机制),在保证业务合理的条件下,俩种方式都可以使用,没有优劣之分。
如果业务对数据一致性要求不高的话,一般更倾向于先更新数据库,在淘汰缓存,更严谨一些的话 采用 先更新数据库,在淘汰缓存;如果业务对数据的一致性要求较高的话,一般 采用先淘汰缓存,在更新数据库,更新完成后在淘汰缓存(延时双删策略)。
解决方案:
1、延时双删策略+设置超时时间
优点:操作比较简单,一定程度可以保证缓存和db数据的一致性
缺点:在休眠时间内数据存在不一致,而且又增加了写请求的耗时
2、基于mysql binglog 日志进行异步更新缓存
基于mysql binglog 的日志进行分析,mysql的操作都会记录在binglog日志中,所以进行分析binglog日志的行为,然后根据不同的行为及业务进行异步更新缓存,可以保证redis缓存和mysql数据库的强一致性;
目前mysql binglog分析工具较多:
开源工具:mysql-binglog=connector-java
ALI Canal:Canal
3、热点数据(或修改较少的常用数据)定时分阶段刷新缓存;增加手动、定时双机制刷新缓存功能(强制刷新缓存功能)
参考链接:
https://developer.aliyun.com/article/712285
https://blog.csdn.net/qq_34125349/article/details/106382286