Redis缓存的使用,极大的提升了应用程序的性能和效率,特别是在数据查询的方便。但是同时也带来了一些问题。其中最要害的问题就是数据一致性问题。从严格意义上来讲这个问题无解。如果对数据的一致性要求极高,那就不能使用缓存了。
另外还有一些典型的问题就是缓存穿透、缓存击穿、缓存雪崩。业界内都有很多的解决方案。接下来就和大家一起了解一下这几种情况以及解决方案。本篇文章并不是完美的解决方案,但是我们可以通过实际编码让大家了解的更加深入。
缓存穿透
缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存的流程大致是,数据查询先进行缓存查询,如果key不存在或者key已过期,在对数据库进行查询,并把查到的对象放进缓存。如果查询对象为空,则不放进缓存。
缓存大致使用流程
代码流程:
- 参数传入对象主键ID
- 根据key从缓存中获取对象
- 如果对象不为空,直接放回
- 如果对象为空,进行数据库查询
- 如果从数据库查询出来的对象不为空,则放入缓存(设定过期时间)
想象一下,如果传入的参数为-1,会怎么样呢???这个-1就是一个一定不存在的对象。每次都要去查数据库,而且每次都为空,每次又都不会存储到缓存。如果有恶意攻击就会抓住这个漏洞,对数据库造成压力,甚至压垮数据库,即便使用uuid,也很容易找到一个不存在的key,进行攻击。
在实际的工作中呢,我们可以采用缓存控制的方式,在上面【代码流程】的第五步,可以将对象为空的也进行一下缓存,只不过过期时间设置的比较短,比如60秒。
缓存空值
缓存雪崩
缓存雪崩,是指在某一时间段,缓存集中过期失效。
产生缓存雪崩的原因之一,比如在写文本的时候,马上到双十二零点,很快就会迎来一波抢购,这波商品的时间比较集中的放入缓存中,假设设置缓存时间为一小时。那么到了凌晨一点的时候,这批商品的缓存就过期了。而对这批商品的访问查询,就全部落到了数据库上,对数据库而言,就会查询周期性的压力波峰。
在实际的电商项目中,一般会采取不通分类商品,缓存不同周期。在同一分类中的商品,加上一个随机因子。这样尽可能分散过期时间,而且,热门类目的商品缓存时间长一些,冷门类的商品缓存时间短一些,也能节省缓存服务资源。
image.png
其实集中过期,倒不是致命的,比较致命的是缓存雪崩,是服务器某个结点宕机或断网。因为自然形成的缓存雪崩,一定是在某个时间段几种创建缓存,那么那个时候数据库能顶住压力,这个时候,数据库也是可以顶住压力的。无非就是对数据库产生周期性的压力而已。而缓存服务结点的宕机,对数据库服务器造成的压力是不可预知的,很可能瞬间就把数据库压垮。
缓存击穿
缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一点进行访问,当key失效的瞬间,持续的大并发就会穿破缓存,直接请求数据库,就像一个屏障开了一个洞。
在电商的项目中,就把这货称为"爆款".
其实,大多数情况下 ,这种爆款情况很难对数据库造成压垮性的压力。达到这个级别的公司没有几家的。所以对主打的商品,可以让其缓存永不过期。即便某些商品自己发酵成了爆款,也是直接设为永不过期就好了。。。
网友评论