如何解决缓存与数据库的数据一致性问题?

1 个回答

  • ketty
    不必太张扬,是花自然香。
    首先需要明白会导致缓存与数据库的数据不一致的几个诱因: 多个写请求的执行顺序不同导致脏数据。 更新时正好有读请求,读请求取到旧数据然后更新上。或者数据库是读写分离的,在主库更新完之后,需要一定的时间,从库才能更新。 **1.先更新数据库,后更新缓存** 1.两个写请求,写请求A,写请求B,A先更新数据库,B后更新数据库,但是可能B会先更新缓存,A后更新缓存,这样就会导致缓存里面的是旧数据。 2.更新缓存时失败也有可能导致缓存是旧数据。 **2.先删除缓存,在更新数据库** 1.删除缓存后,更新数据库之前假如正好有读请求,读请求把旧数据设置到缓存了。 **3.先更新数据库,再删除缓存** 1.更新后删除缓存时,网络不好,删除失败也有可能导致缓存是旧数据。 2.写请求A更新数据库然后删除缓存,读请求B读数据时发现缓存中没有数据,就从数据库拿到旧数据准备设置到缓存上去时,如果整个架构是读写分离的,写请求更新数据是在主库上更新,读请求B是去从库上读数据,如果此时主库上的新数据还没有同步到从库,这样读请求B在从库读到旧数据,设置到缓存上,导致缓存里面是旧数据。 **正确的方案** **1.写请求串行化** 将写请求更新之前先获取分布式锁,获得之后才能更新,这样实现写请求的串行化,但是会导致效率变低。 2.先更新数据库,异步删除缓存,删除失败后重试 先更新数据库,异步删除缓存,删除缓存失败时,继续异步重试,或者将操作放到消息队列中,再进行删除操作。(如果数据库是读写分离的,那么删除缓存时需要延迟删除,否则可能会在删除缓存时,从库还没有收到更新后的数据,其他读请求就去从库读到旧数据然后设置到缓存中。) ![image.png](https://images.codewd.com/0c88d434c18f6279d90d351f066a3975.png) ### 3.业务项目更新数据库,其他项目订阅binlog更新 业务项目直接更新数据库,然后其他项目订阅binlog,接收到更新数据库操作的消息后,更新缓存,更新缓存失败时,新建异步线程去重试或者将操作发到消息队列,然后后续进行处理。但是这种方案更新mysql后还是有一定延迟,缓冲中才是新值。 参考资料:[https://www.cnblogs.com/rjzheng/p/9041659.html](https://www.cnblogs.com/rjzheng/p/9041659.html)
    发布于 2022-02-13 10:01 •IP属地 云南
    举报
    评论
    收藏