缓存与数据库双写一致性问题

之前在脉脉上看到有关这个问题的描述,大体看了下。这两天放假有空 特地看下关于这个问题的解决方案。要解决这个问题 首先要知道一个模式就是cache aside pattern,这是外国大佬提出的一个概念。

Cache Aside Pattern
1.读操作.判断缓存是否存在,不存在读取数据库中的信息并更新缓存。存在的话读取缓存中的信息
2.写操作.更新数据库,删除缓存。

扯到这个问题,会出现很多问题,比如为什么是删除缓存,而不是更新缓存。
为什么是先更新数据库,再删除缓存,而不是先删除缓存,再更新数据库的问题。网上看到很多有关这种问题的解释。这里简单的记录下.

为什么是写操作的时候是删除缓存而不是更新缓存?

  1. 如果 系统中频繁的进行写操作,而读操作很少的话,那么就是进行大量的数据修改,造成系统吞吐的下降(1分钟内下单100笔,如果按照双更新操作,那么就需要更新100次缓存数据。而如果更新数据库,删除缓存的话,只需要在读的时候进行一次缓存更新操作即可,这样效率上无疑是更高的)
  2. 同时很多时候 缓存数据并不是直接从一张表就能够查到的,有时需要关联多张表才能查询到数据。(典型的就比如 商品库存数量,不仅要查询商品库存还有已经下单的但还未支付的也要计算其中存入缓存中)

实际上这就是一个惰性思维的体现,类似于单例模式中的懒加载,通过空间换时间的概念,修改数据的时候 我们不更新缓存数据,只有他在用到的时候 才进行缓存更新操作。同时即使有大量的读操作进来,实际上也只是更新了一次,后面的请求不会重复读的。

双写一致性问题的产生
Cache Aside Pattern写操作采用的是先更新数据库,后删除缓存的解决方案,网上资料看到现在facebook就是采用的这种技术解决方案。暂时不考虑这种方案,因为目前看这种方案如果在写操作更新数据库的时候出现查询操作导致 将读取旧的数据,那样就会出现读写冲突问题。 这里来采用 先删除缓存后更新数据库的解决方案。

先删除cache再更新db的原因
如果先删除缓存然后更新数据库,理论上是无论删除缓存失败还是更新失败,数据库与缓存数据都会保持一致。

  1. 缓存删除失败:删除缓存失败,那么数据库信息也没有修改,保持了数据的一致性。
  2. 缓存删除成功,数据库删除失败:此时查询数据发现缓存不存在,查询数据库的数据,更新缓存,数据还是一直的.

在这里插入图片描述
先删除cache再更新db存在的不足
写操作 删除完缓存更新数据库操作的时候,如果一个请求过来 查询数据,缓存不存在,查询数据库中的旧数据,更新旧数据到缓存中。此时就会出现读写冲突的问题。那么如何解决这一方案出现的问题那?

该方案不足的解决方法

  1. 理论上只需将写操作时的数据 作为唯一标识放入jvm内部队列中去,在读操作时判断内部队列中是否存在写操作,如果存在写操作,那么等待写操作完成 才去进行数据的读取。(同时如果多个读请求过来,如果发现前面有读请求操作,直接用前面的数据就好了)
  2. 通过双删除策略保证在 更新数据库中没有错误的缓存数据被更新,具体方法就是先删除缓存 ,更新数据库后,线程休眠1秒,然后再删除缓存一遍。通过双删除策略 可以保证你在读取错误数据及时的被修正过来(可以将线程休眠再删除缓存进行异步操作,启用一个线程去执行第二次删除缓存的操作)

总结来看
目前网上关于数据库与缓存双写一致性的方案有很多,但本质上来讲都是为了避免出现缓存与数据库不一致发生的概率。现在的项目中用到缓存才能的地方有以下几个地方

  1. redis作为非关系数据库 存储客户购买电池片编号存储的集合
  2. 利用redis中的zset数据结构作为排行榜实现的解决方案
  3. redis作为存储客户购买电池片数量及金额的缓存(但是查询的时候还是用的数据库商品订单表作为数据源)

之前项目中的主要疑问

  1. 客户购买电池片成功的时候,因为有一个主动查询与微信通知 支付结果,所以容易产生线程冲突的问题,后面决定把主动查询改为购买成功,而不去主动查询 操作。(现在看的话 之前项目经理推荐的使用数据库锁机制,如果有线程开始处理这个资源前,先判断是否存在数据库锁记录,不存在添加锁记录,处理完成或发生异常 删除锁记录。如果存在锁记录,等待一会再去处理)
  2. 另一个问题就是关于一个业务员方法中存在着 更新数据库与更新缓存的2个操作过程,现在看起来实际上没什么必要,应该利用cache aside pattern的模式 在读取的时候不存在缓存的时候更新上去,不然更新的时候 系统吞吐下降的太厉害了

参考网友资料链接

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值