如何保证缓存(redis)与数据库的一致性

针对这两点问题,一共可以分为四种方案:
  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

posted @ 2022-02-16 16:00  跟着心走!  阅读(2445)  评论(1编辑  收藏  举报