侧边栏壁纸
博主头像
再见理想博主等级

只争朝夕,不负韶华

  • 累计撰写 112 篇文章
  • 累计创建 64 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

缓存数据库一致性方案

再见理想
2022-06-15 / 0 评论 / 0 点赞 / 367 阅读 / 927 字

前言

我们通常使用缓存机制来提升系统的性能,缓存系统下的读写操作,一般都需要操作数据库与缓存。对于读操作,一般是先查询缓存,查询不到再查询数据库,最后回写进缓存。
而对于写操作,存在刷脏的问题,可以根据业务对一致性的要求,选择对应的方案,达到数据的最终一致性。

写操作常用的几种方案

方案一:先更新数据库,再更新缓存


缺点:写多读少时,频繁更新缓存会降低性能;并发情况下可能存在将脏数据写回缓存的风险;

方案二:先更新缓存,再更新数据库;

同方案一,存在将脏数据写回缓存的风险;

方案三:先更新数据库,再删除缓存;


首先系统处于一个缓存过期的初始状态,接着读写并发。由于读请求读到了数据库的旧值,而由于某种原因,回写发生在写请求执行完毕之后,造成了刷脏的问题。
这种问题发生的概率较低,首先缓存得过期,再者读请求的整条链路的执行速度慢于写请求。一般来说,读肯定是快于写的。不要求很高一致性的话,推荐此方案。

方案四:先删除缓存,再更新数据库;


写请求删除缓存后,读请求无法命中缓存,因此读到数据库的旧值2。写请求更新完数据库后,读请求再将1回写进缓存,同样存在刷脏的风险。
该问题发生的概率一般会高于方案三,那如何去解决呢?可以采用延时双删方案;

方案五:延迟双删;


此方案的难点在于,sleep的时间该怎么去确定。如果偏大,同步删除的话会造成吞吐量的降低与查脏。如果偏小,则有可能第二次删除在刷脏之前发生,起不到“双删”的作用。

方案六:消息队列;


先更新数据库,接着将删除缓存的消息投递到mq中。自身拿到消息后,尝试进行删除缓存。如果失败,则不断进行重试。
该方案会对业务代码造成一定的侵入,但避免了刷脏的问题,保证数据的最终一致性。

方案七:canal+消息队列


业务代码只操作数据库,不操作缓存。在MySQL中,可以使用canal中间件来订阅binlog,当监听到删除操作,将投递到消息队列中,消费者监听到消息队列的消息后作删除缓存操作。
该方案会对业务代码造成一定的侵入,但避免了刷脏的问题,保证数据的最终一致性。

总结

可以根据业务对数据一致性的要求去选择对应的方案,如果对一致性要求不是很高,建议采用 方案三 先更数据库,再删缓存方案,能很大程度上避免刷脏的问题;
如果要完全避免刷脏问题,建议采用方案六 消息队列或方案七 canal+消息队列的方案。

0

评论区