缓存双写一致性

发布时间 2023-06-14 15:04:19作者: 上好佳28

几种方案

1、先更新数据库,再更新缓存(不可行)

该方案会导致不一致,如:

(1)线程A更新了数据库 (2)线程B更新了数据库 (3)线程B更新了缓存 (4)线程A更新了缓存

B却比A更早更新了缓存,这就导致了脏数据,不可行

2、先删缓存,再更新数据库

该方案会导致不一致的原因是。同时有一个请求A进行更新操作,另一个请求B进行查询操作。那么会出现如下情形: (1)请求A进行写操作,先删除缓存 (2)请求B查询发现缓存不存在 (3)请求B去数据库查询得到旧值 (4)请求B将旧值写入缓存 (5)请求A将新值写入数据库

这种情况可以采用延迟双删策略,即休眠1秒,再次淘汰缓存

3、先更新数据库,再删缓存

该方案会导致不一致的情况:

(1)缓存刚好失效 (2)请求A查询数据库,得一个旧值 (3)请求B将新值写入数据库 (4)请求B删除缓存 (5)请求A将查到的旧值写入缓存

上面情况发生的条件,就是步骤(3)的写数据库操作比步骤(2)的读数据库操作耗时更短,这很难出现

因此实际上这种方案也是可行的

其次也可采用方案二里给出的异步延时删除策略

如果删除缓存失败了怎么办?

重试机制

方案一:

(1)更新数据库数据; (2)缓存因为种种问题删除失败 (3)将需要删除的key发送至消息队列 (4)自己消费消息,获得需要删除的key (5)继续重试删除操作,直到成功

对业务线代码造成大量的侵入

方案二

(1)更新数据库数据 (2)数据库会将操作信息写入binlog日志当中 (3)订阅程序提取出所需要的数据以及key (4)另起一段非业务代码,获得该信息 (5)尝试删除缓存操作,发现删除失败 (6)将这些信息发送至消息队列 (7)重新从消息队列中获得该数据,重试操作。

上述的订阅binlog程序在mysql中有现成的中间件叫canal,可以完成订阅binlog日志的功能