单机缓存_如何处理缓存一致性,缓存穿透,缓存雪崩,缓存并发解决方案

最近在做架构使用redis做缓存,碰到了一些问题,考虑数据量很大的时候,会遇到的几个问题:

1a00be4b1ae1cb7bd449665832a2d4d1.png

1. 关于缓存一致性

当我们更新了数据库的数据,先删除缓存,然后在更新数据库,如果删除缓存失败,那就不要更新数据库,如果说删除缓存成功,而更新数据库失败,那查询的时候只是从数据库里查了旧的数据而已,这样就能保持数据库与缓存的一致性。要求高的场景下,使用实时更新策略-即数据有变化时,更新的线程直接同步缓存数据如果允许,可以单独架设第三方方案,来同步缓存数据,常见的有发布订阅/MQ(例如rabbitmq)方式容忍度较高的场景,可使用缓存过期策略 --- 允许数据短期不一致,定时任务,适合数据变化特别不频繁的情况。

2.缓存穿透的情况

缓存穿透查询一个数据库中不存在的数据,每次都会访问DB,如果有人恶意破坏,很可能直接对DB造成过大地压力, 缓存被穿透。在流量大时,可能DB就挂掉了。

方案:第一如果一个查询返回的数据为空,不管是数据不存在还是系统故障,我们仍然把这个结果进行缓存,但是它的过期时间会很短,最长不超过5分钟。第二是根据key获取value值为空时,锁上,从数据库中load数据后再释放锁。若其它线程获取锁失败,则等待一段时间后重试。这里要注意,分布式环境中要使用分布式锁,单机的话可以使用普通的锁(synchronized、Lock).第三是使用BloomFilter,是一个占用内存空间比较小而且效率很高的随机数据结构,它由一个bit数组和一组Hash算法构成。在java中可以使用guava中的bloom Filter,它可以用于判断一个元素是否在一个集合中。

3.缓存雪崩的情况

缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。在同一时间内大量键过期(失效),接着来的一大波请求瞬间都落在了数据库中导致连接异常。

方案:第一是将系统中key的缓存失效时间均匀地错开,防止统一时间点有大量的key对应的缓存失效。比如可以在原有的失效时间基础上增加一个随机值,比如几分钟随机,这样每一个缓存的过期时间的重复率就会降低。第二是增加互斥锁,控制数据库请求,重建缓存。加锁排队只是为了减轻数据库的压力,但并没有提高系统吞吐量。使用锁或队列、设置过期标志更新缓存、为key设置不同的缓存失效时间。第三是设置redis集群和DB集群的高可用,如果redis出现宕机情况,可以立即由别的机器顶替上来。这样可以防止一部分的风险。

4.缓存并发问题

多个redis的client同时set key引起的并发问题,由于redis自身是单线程操作,多个client并发操作,按照先到先执行的原则,先到的先执行,其余的阻塞。当然,另外的解决方案是把redis.set操作放在队列中使其串行化,必须的一个一个执行,当然加锁也是可以的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值