栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

浅谈缓存数据库双写一致性

浅谈缓存数据库双写一致性

1. 事务完善双写一致性

17boot-cache引入了@Cachemeta来标注缓存,但是spring的已经有现成的缓存,为什么要新写一个注解去做这个事呢,在cf中提出了一个场景,@Cachemeta就是为了解决这个问题:

1 thread-1 根据id删除表中数据
2 thread-1 根据id清除缓存
3 thread-2 根据id从缓存中查找数据
4 thread-2 缓存中找不到,查询数据库,拿到的是老数据,并加载到缓存
5 thread-1 事务提交

在这个情况下,thread-1拿到就是thread-2放入的旧数据

那如何解决这个问题,他们给出了以下方法

1 thread-1 根据id删除表中数据
2 thread-1 标记该id需要删除 // 只是标记,还未真正发起对缓存的操作
3 thread-2 从缓存中查找数据,找到缓存,返回
4 thread-1 事务提交
5 thread-1 调用spring事务成功回调方法,正式清除该id对应的缓存

Cachemeta的解决方法是事务未结束时对缓存数据进行标记删除,只有当事务返回成功之后才会正式清除对应的缓存。其中标记删除可以进行批量操作,减少交互。

其实这个问题是经典的并发下的问题:如何保障数据库缓存双写一致性

2.数据库缓存双写一致性解决方案 2.1 删除缓存还是更新缓存?
  1. 线程A先发起一个写操作,第一步先更新数据库
  2. 线程B再发起一个写操作,第二步更新了数据库
  3. 由于网络等原因,线程B先更新了缓存
  4. 线程A更新缓存。

这时候,缓存保存的是A的数据(老数据),数据库保存的是B的数据(新数据),数据不一致了,脏数据出现啦。如果是删除缓存取代更新缓存则不会出现这个脏数据问题。

更新缓存相对于删除缓存,还有两点劣势:

  • 如果你写入的缓存值,是经过复杂计算才得到的话。更新缓存频率高的话,就浪费性能啦。
  • 在写数据库场景多,读数据场景少的情况下,数据很多时候还没被读取到,又被更新了,这也浪费了性能呢(实际上,写多的场景,用缓存也不是很划算了)
2.2 先删除缓存还是先更新数据库?

我们在操作缓存的时候,到底应该先删除缓存还是先更新数据库呢?我们先来看个例子:

  1. 缓存已经失效
  2. 线程A查询数据库,得一个旧值
  3. 线程B将新值写入数据库
  4. 然后线程B删除缓存
  5. 线程A将查到的旧值写入缓存

一般来说读比写快很多,第二步和第五步之间插入写动作概率不大。

2.3 先删除缓存,再更新数据库
  1. 线程A先发起一个写操作,先删除了缓存
  2. 线程B再发起一个读操作,发现缓存不存在
  3. 线程B查询旧值后放入缓存
  4. 线程A更新了数据库

缓存和数据库的数据不一致了。缓存保存的是老数据,数据库保存的是新数据。因此,Cache-Aside缓存模式,选择了先操作数据库而不是先操作缓存。

解决方法:

  • 先删除缓存,再更新数据库,休眠一会再删缓存(双删,第二次删可异步)

这个休眠时间 = 读业务逻辑数据的耗时 + 几百毫秒。 为了确保读请求结束,写请求可以删除读请求可能带来的缓存脏数据。

2.3.1 删除缓存重试机制

不管是延时双删还是Cache-Aside的先操作数据库再删除缓存,如果第二步的删除缓存失败呢,删除失败会导致脏数据哦~

删除失败就多删除几次呀,保证删除缓存成功呀~ 所以可以引入删除缓存重试机制

  1. 写请求更新数据库
  2. 缓存因为某些原因,删除失败
  3. 把删除失败的key放到消息队列
  4. 消费消息队列的消息,获取要删除的key
  5. 重试删除缓存操作
2.4 17boot-cache解决了什么

对于2.3的情况,第一步A的事务没有结束,所以@Cachemeta并没有删除缓存,所以第二步B去读还是能读到缓存,避免了将缓存更新成旧缓存的问题。

但是还是无法避免2.2的情况,其实先操作db还是cache,都会有各自的问题,根本原因是cache和db的更新不是一个原子操作,因此总会有不一致的问题。想要彻底解决这种问题必须将cache和db的更新操作归在一个事务之下(例如使用一些分布式事务,或者强一致性的分布式协议),可能反而得不偿失。

在RedisCacheManager中设置transactionAware也能实现

加入template.setEnableTransactionSupport(true);即可打开redis事务

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/316337.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号