缓存相关-先埋个坑后续填补

说到缓存,离不开一些概念:缓存击穿,缓存穿透,缓存雪崩。谈谈我我的对这些概念的理解吧。web

  • 缓存穿透

请求没有访问到缓存,而是直接访问到了数据库层面,可是数据库层面也没有返回数据。
这种状况不少都是恶意攻击的时候出现的。复制代码

场景:有个商品详情的接口/goods/{id},通常id都是数据库自增的,从1开始,如/goods/1。假若有个/goods/-1的请求过来了, 因为数据库中不存在-1的商品信息,天然在缓存里也不会去缓存这样的数据,所以这样的请求就可能会直接访问到数据库,当有大批量的相似请求并发访问的时候,就有可能会给数据库形成压力,致使性能瓶颈。数据库

解决办法

1. 参数校验。好比校验id是否合法,id < 1的直接过滤掉。缓存

2. 降级方案是针对这些不合理的id作缓存,即,在数据库层访问结束后假如没有查到数据,则把这些id缓存下来,相似于作黑名单id同样,等下次再来访问的时候先检查id是否在黑名单id列表里,在的话就不要走后面的流程,直接返回。这种方案的缺点是只能拦截id相同的,假如一直用不一样的id去访问的话,那黑名单id列表会不断的增大,致使缓存吃紧bash

  • 缓存击穿

请求访问过来的时候,恰好缓存处于失效状态,致使高并发的请求访问到了数据库层面,数据库有可能会所以而资源紧张。复制代码

场景:商品详情的请求 /goods/1 访问的时候,恰好 id=1 的缓存处于失效状态,致使该请求直接访问了数据库,数据库返回了 id=1数据 并发

解决办法

1. 不设置缓存失效时间,异步刷新缓存数据。即,当有请求过来的时候,检查缓存的有效状态,假如缓存状态是已失效,能够经过发送异步消息给后台,经过后台去刷新缓存数据。本次请求依旧返回缓存中的失效数据。app

2. 能够设置缓存失效时间,可是经过加锁的方式刷新数据。即,当请求过来的时候,假如缓存中没有数据,则经过加锁的方式让请求排队,只容许一个请求去访问到数据库,防止并发访问,数据库返回数据后存到缓存当中,释放锁,第二个请求进来的时候判断是否缓存中已有数据,有的话直接读取。这种方案可能须要限制并发次数,避免大量请求排队致使web容器的链接池爆满,影响别的业务请求。异步

  • 缓存雪崩
指的是大量缓存在同一时刻失效的现象,致使各类请求访问的时候都没有读取到缓存的数据,而是全都访问了数据库。复制代码

场景:同时有商品数据、订单数据等缓存数据在同一瞬间失效,用户的访问请求全都直接访问到了数据库,数据库可能在瞬时承受着极高的并发访问。 
高并发

解决办法

1. 各类业务数据在设置缓存失效时间的时候,不要选择相同的失效时间,能够选择错峰失效的方式,好比选择夜深人静访问量少的时候失效,或者给失效时间再加个随机值,不要在整点时刻失效,好比选择在xx点xx分23秒的时候失效,避免缓存数据瞬间大量失效。性能

2. 缓存不要失效,异步刷新数据。ui

  • 总结

缓存穿透和缓存击穿有点相似,不一样之处在于缓存穿透不少状况下是恶意访问致使的,而缓存击穿是内部缓存策略致使的。

缓存击穿和缓存雪崩都是内部缓存策略致使的,不一样之处在于缓存击穿是某个点上的缓存问题,而缓存雪崩是一大片一大面的。点和面的区别。

相关文章
相关标签/搜索