Redis与数据库数据的一致性

Redis与数据库数据一致性

普通情况下的解决方案(Cache Aside Pattern)
  1. 读的时候先读缓存,如果没有,再读数据库,最后刷新缓存
  2. 更新的时候,如果该数据会被再次频繁地访问到,我们就要把数据刷新回缓存,如果不怎么被访问,我们可以删除缓存,再更新数据库,这种事Lazy计算的一个思想。
28法则

​ 20%的数据占用了 80%的访问量,高并发主要在20%的数据当中,另外的那些不经常被访问的数据,如果我们要更新的话,我们可以直接删除缓存,再更新数据库。等到要用的时候,我们才会将缓存重新存回到redis当中。因为经常刷新缓存是十分浪费redis资源的。

高并发下的缓存与数据库双写不一致的问题的解决方案与设计

1. 先修改数据库再删除缓存,但是万一缓存删除失败呢?

解决方案:先删除缓存,再更新数据库,即使数据库更新失败,缓存是空的,那么数据也不会不一致,此时读到没有缓存,则会读取数据库中的旧数据,然后更新到缓存当中。

2. A请求修改数据,先删除缓存再修改数据库,此时还没修改,B请求过来去读缓存发现缓存是空的,去查数据库,查到了修改前的旧数据,放回了缓存当中。之后数据库又被A修改了,缓存放的是旧数据,而数据库放的是新的数据,造成了不一致的问题。

解决方案:数据库与缓存的更新进行异步串行化

更新数据的时候,根据数据的唯一标识(hash路由),将操作路由之后,发送到JVM的一个内部队列当中,然后每个内存队列对接一个后台线程,后台线程再对缓存跟数据库进行处理。

A请求的操作有A1 (删除缓存) A2(更新数据库) ,B请求的操作有B1(读取数据) ,那么A1跟A2先后进去内存队列当中,然后执行,当A1 或者A2正在执行的时候,B1来了,则会先进去队列当中,排到了A2后面,此时B1在内部实际上是等待A1, A2完成后才执行,这样一来就能保证缓存与数据库数据一致性的问题。

关键是需要使用hash路由,使得对同一个数据的操作落到同一个消费者上面串行化。

不过,要注意的是,如果短时间内多个请求都要读取同一个数据,会有很多个相同的读操作压入队列当中,从而阻塞队列,所以我们在读请求压入队列之前先判断,队列的尾部如果也是读请求,而且是读同一个数据,则不压入队列,而是选择等待缓存被更新,一定时间过后(通常是你的系统最低响应时间)直接读缓存而不用经过消费者,相反如果是写操作,才压入队列。当然,如果有非常多的写操作积压在队列中,就会导致读操作的响应时间非常慢,所以这时候就要增加更多的机器,这样可以减少积压,通过hash路由后,每个队列都能分散到压力。

但是,异步串行化之后系统的吞吐量会降低,而且会需要更多的机器去支撑,如果严格要求强一致性,最好不要使用缓存。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值