首先考虑单删的问题

先删

先删在两个线程的并发下,就可能会出现缓存与数据库数据不一致的问题

先删

后删

后删可以在一定程度上解决两个线程并发下的缓存与mysq不一致的问题

后删

但是在线程数超过两个,达到三个的时候,仍有可能出现数据库数据与缓存数据不一致的问题,无法保证最终一致性,线程A修改数据,删除缓存后,线程B读取数据库数据,放入缓存前,线程C修改了数据,在线程C未删除缓存后,线程B操作缓存写入,导入数据库缓存不一致。
三线程后删问题

延时后删

采用延时后删,在并发场景下,只要延时时间合适,一定可以避免线程B将错误数据加载到缓存中的场景(缓存删除前一直读缓存数据,缓存删除后,读事务提交后的数据,出现后删中三线程并发下的缓存与mysql数据不一致场景的可能性不大),可以保证最终一致性,但是在延时删除期间,线程B会长时间读取到旧数据,这在一些场景下无法接受的。

延时后删

接着考虑双删

双删

仅仅双删,在两个线程并发的场景下,就无法保证缓存与mysql的最终一致性

双删

延时双删

伪代码
public void 延时双删{
    // 减少延后删除导致的其他线程读取老数据的尝尽出现。
    delCache(key);
    updateMysql(data);
    // 解决缓存与mysql无法保证最终一致性的问题。
    sleep(time);
    delCaChe(key)
}
极端场景

极端情况下,延时双删,也无法避免某个线程长时间读取老数据的问题,但是通常删除缓存与更新数据库操作的间隔比较短,所以出现这种场景的概率不是很大。

延时双删极端场景

总结

采用延时双删,是为了在保证数据库与缓存数据最终一致性的情况下,尽可能的减少查询老数据场景出现的可能性。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐