如何解决数据更新导致缓存一致性问题?

如何解决数据更新导致缓存一致性问题?

一.为什么使用分布式缓存

我们初步了解了什么是缓存以及一般的缓存使用逻辑,那么为什么要使用分布式缓存呢?

在服务架构初期我们基本上都是单体架构,一个tomcat服务器撑起一片天,可能只需要基于本地内存存储进行缓存即可。但随着架构的演进,由单体SOA架构闫金成分布式架构之后,如果还使用本地缓存,那么就会导致多台服务器上缓存不一致,数据无法共享问题。因此基于这种问题,分布式的缓存由此诞生。当前分布式缓存最常用的工具还是redis和memcached。
如何解决数据更新导致缓存一致性问题?_第1张图片

二.缓存过期以及一致性问题

读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容 易出现缓存(Redis)和数据库(MySQL)间的数据一致性问题。

讨论一致性问题之前,先来看一个更新的操作顺序问题:

先删除缓存,再更新数据库

问题:同时有一个请求 A 进行更新操作,一个请求 B 进行查询操作。 可能出现:

( 1)请求 A 进行写操作(key = 1 value = 2) ,先删除缓存 key = 1 value = 1

( 2)请求 B 查询发现缓存不存在

( 3)请求 B 去数据库查询得到旧值 key = 1 value = 1

( 4)请求 B 将旧值写入缓存 key = 1 value = 1

( 5)请求 A 将新值写入数据库 key = 1 value = 2

缓存中数据永远都是脏数据

我们比较推荐操作顺序:

先删除缓存,再更新数据库,再删缓存(双删,第二次删可异步延时)

public void write(String key,Object data){

redis.delKey(key);

db.updateData(data);

Thread.sleep(500);

redis.delKey(key);

}

接下来,看一看缓存同步的一些方案,见下图:
如何解决数据更新导致缓存一致性问题?_第2张图片

2.1.数据实时同步更新

方法:更新数据库同时更新缓存,使用缓存工具类和或编码实现。

优点:数据实时同步更新,保持强一致性

缺点:代码耦合,对业务代码有侵入性

2.2.数据准实时更新

准一致性,更新数据库后,异步更新缓存,使用观察者模式/发布订阅/MQ 实现;
如何解决数据更新导致缓存一致性问题?_第3张图片

优点:数据同步有较短延迟 ,与业务解耦

缺点:实现复杂,架构较重

2.3.缓存失效机制

弱一致性,基于缓存本身的失效机制

优点:实现简单,无须引入额外逻辑

缺点:有一定延迟,存在缓存击穿/雪崩问题

2.4.定时任务更新

最终一致性,采用任务调度框架,按照一定频率更新

优点:不影响正常业务

缺点:不保证一致性,依赖定时任务

2.5.各方案实现总结

方案名称 技术特点 优点 缺点 适用场景
数据实时 同步更新 强一致性,更新数据库同时更新缓存,使用缓存工具类和或编码实现 数据一致性强 代码耦合 运行期耦合 影响正常业务 数据一致实时性要求比较高的场景,如:银行业务、证券交易;
数据准实时更新 准一致性,更新数据库后,异步更新缓存,使用观察者模式/发布订阅/MQ实现; 数据同步有较短延迟 与业务解耦 不影响正常业务 实现复杂,架构较重 不适合写操作频繁并且数据一致实时性要求严格的场景;
缓存失效 机制 弱一致性,基于缓存本身的失效机制 实现简单 有一定延迟 不保证强一致性 存在缓存雪崩问题; 适合读多写少的场景,能接受一定数据延时;
任务调度 更新 最终一致性,采用任务调度框架,按照一定频率更新; 不影响正常业务; 不保证一致性 依赖定时任务 容易堆积垃圾数据; 适合复杂统计类数据缓存更新,对数据一致实时性要求低的场景;如:统计类数据,BI分析等;

你可能感兴趣的:(分布式,缓存一致性,分布式缓存,数据一致性问题,架构演进,redis)