缓存的理解

1.系统为什么要引入缓存?引入缓存会带来哪些好处?

缓存有一定的适用场景,需要合理地使用。引入缓存有两个主要目的:

引入缓存可以提高响应速度。对于读多写少的系统,如果没有缓存,每个请求都需要打到Mysql数据库去查询,有的在查询之后还需要经过一系列复杂的计算才能得出用户想要的结果,这样每个请求都是走一遍全链路,系统做功很多,存在大量磁盘IO,系统压力很大。如果引入缓存,缓存可以把热点数据或一些需要经过复杂计算得到的结果数据进行缓存,那么缓存就相当于是一个“短路”的作用,系统走了“捷径”,只需要查一次库,然后把结果缓存下来,之后的所有类似的请求可以直接拿取这个结果就行了,避免了系统大量做功。

引入缓存可以提高系统并发性。Mysql单机的TPS大概为2000/s,最高不超过5000/s,即使通过分库分表,在增加系统复杂度的同时并发也不会有很大的提升。但是redis这样的缓存系统TPS可以达到万级每秒,通过缓存可以避免大量读请求打到数据库中,会大大提高系统并发量。

2、引入缓存会产生哪些问题?

数据库与缓存一致性问题、缓存雪崩、缓存穿透、缓存击穿

数据库与缓存一致性问题:

常用的数据库与缓存更新方式有:

数据库与缓存双写:无论是先写数据库后写缓存,还是说先写缓存后写数据库。不符合懒加载思想。

先删除缓存后更新数据库:高并发的情况下,A线程删除了缓存,B线程因为方式缓存因没有数据把数据库种旧的值又刷到了缓存种,之后A线程才把数据更新到数据库。出现了缓存不一致。

先更新数据库后删除缓存:这种方式我觉得没有什么问题,但是有人会说,如果删除缓存失败怎么办?我就想问,删除缓存这个动作怎么就会失败呢?我理解的是,不是说删除缓存这个动作没有执行成功,而是数据库的MVCC机制导致一个现象:在极少数特殊的时刻,你读取到的数据只是一个历史快照,那么A线程更新数据库其实已经成功了并删除了缓存,但是B线程在A线程删除缓存之后并且在A线程所执行的事务还没有提交的时候,读取了更新的数据的历史快照(因为事务隔离级别是可重复读的),那么会导致快照被刷入缓存,出现了“数据库更新成功,缓存删除失败”的假象而已。所以我认为应该加个附加条件:在更新数据库的事务提交之后删除缓存。

缓存雪崩

现象:指的使缓存的大面积失效。

原因:缓存雪崩的原因有很多,比如redis集群挂了,redis重启后没有缓存预热等等,缓存雪崩后果很严重,大量请求打到数据库中,把数据库到死,没有数据库整个后台系统就都不可用了,即使重新启动数据库,也会因为没有缓存重新被打死。

解决方案:缓存的解决方式从三个层面:

事前解决方案:保证redis集群是高可用的,部署方式得是 redis replication + sentinal,或 redis cluster。

事中解决方案:制定多级缓存架构,比如使用ehcache;使用限流+降级机制,保证数据库不会被打死。限流就是如果每秒有5000个请求过来,但数据库每秒只能承受2000个请求,那么限流只会允许2000个请求打到数据库,剩下3000个请求不允许通过;降级指的是让剩下的3000个请求走降级路径,可能是一个友好提示,或是返回空值等等。

事后解决方案:这就是说如何在缓存雪崩后快速对redis集群进行恢复,不仅仅是重新启动redis集群,还包括快速缓存预热。这也就是为什么缓存需要持久化的原因,可以选择使用rdb文件快速对缓存进行预热。

缓存穿透

现象:用户访问了一个数据库中不存在的数据,数据库中没有,所以缓存中自然就不会有,所以每次这样的请求重复进行,每次都发生缓存穿透。在并发量大的情况下,还是可能把数据库打死。

解决方案:

使用布隆过滤器,布隆过滤器保证了如果匹配成功,那么可能在系统的数据范围内,如果匹配不成功,那么一定不在系统的数据范围内。布隆过滤器的作用就是排除掉一些些不合理的请求。

缓存NULL值:感觉布隆过滤器还是不能根本性的解决缓存穿透的问题,所以最终极也是最简单的方法就是:如果数据库中没有查到数据,那么就把这样的信息也保留到缓存中,下次再来的时候,缓存直接告诉你没有,而不是每次都打到数据库中。当然为了避免说,本来没有的数据后来有了,缓存null值必须设置过期时间。

缓存击穿:

现象:就是说某个 key 非常热点,访问非常频繁,处于集中式高并发访问的情况,当这个 key 在失效的瞬间,大量的请求就击穿了缓存,直接请求数据库,就像是在一道屏障上凿开了一个洞。

解决方案:可以将热点数据设置为永远不过期;或者基于 redis or zookeeper 实现互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其它请求才能通过该 key 访问数据。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值