缓存一致性问题

2022-12-23  本文已影响0人  贪挽懒月

一、什么是一致性问题

为了提升服务的性能,我们一般会把热点放进缓存,那么这些热点数据就同时存在于数据库和缓存中,缓存中的数据和数据库中的数据要保持一致,这便是缓存一致性问题。

二、使用缓存存在的问题

加了缓存之后,读写流程大概如下:
1. 读流程

读数据流程

2. 写流程

写数据流程

3. 写操作的应该更新缓存还是删除缓存
答案是应该删除缓存,如果是更新,可能会有如下问题:

更新缓存的问题

如上图所示,如果线程 A 先更新了 DB,接着线程 B 更新 DB,正常情况,缓存中保存的应该是线程 B 写入 DB 的数据,但因为最后是线程 A 去更新的缓存,因此导致 DB 和缓存中的数据不一致。

4. 既然要用删除,删除操作在更新DB之前还是之后呢
答案是之前,如果是之后,可能会出现如下问题:

先写DB的问题

如果先更新 DB,在更新了 DB 之后,还没来得及删除缓存之前,线程 B 读请求进来了,那么读取到的是缓存中的旧数据,也会出现一致性问题。

5. 先删除再操作DB就没问题吗
答案是也会有问题,可能会出现如下场景:

先删缓存的问题

线程 A 先删除了缓存,还没来得及更新 DB 的时候,线程 B 进来了,把 DB 中的旧数据又读取到了缓存中,最后线程 A 更新了 DB,数据还是不一致。

三、缓存一致性问题的解决方案

1. 双删延迟策略
上面说了先删除缓存还是会存在问题,就是线程 A 更新 DB 之前如果线程 B 把数据读到缓存中了,数据也会不一致。双删延迟策略就是更新了 DB 后休眠一段时间再次删除缓存,如下:

双删延迟策略

2. 使用binlog异步删除缓存
我们知道,DB 的操作一般都会记录到日志中,比如 MySQL,所有的写操作都会记录到 binlog 中,那么我们可以通过 binlog,去删除缓存。canal 就是一款用来解析数据库日志的工具,我们可以接入 canal,采集到日志,然后通过 MQ 异步的去删除缓存,这样对业务代码就没有入侵了。异步删除缓存流程如下:

binlog异步删除缓存
上一篇下一篇

猜你喜欢

热点阅读