关于redis缓存数据库的一些思考

101 阅读6分钟

今晚无聊,躺在床上,在刷技术文章时,看见了一篇关于redis缓存的文章 写的蛮好,这也就引起了我对于redis思考!

不如往深了说 引起了我对于追求探索技术本质的一些思考 平时在网上刷到很多关于redis的文章,我也在项目中经常用到redis这个缓存数据库 记得自己初学redis时 总是纠结技术如果去学 但是随着阅历以及学习能力和经验的提高 自己也对技术也有一些悟出来的道理 或者说是如何学好技术 往后有时间或者哪天心血来潮了写一篇关于自己对于技术的认知

还是进入主题,在网上经常刷到关于redis的文章,自己也经常在项目中用到redis,但是自己从来没有太过深究redis,心里老觉得不得劲 于是今晚就心血来潮了写一篇关于自己对redis的一些思考

这里我就不说redis是干什么的了,如果不知道看下我之前写的redis文章,这些文章中也有官网的内容 因为我也是从官网学的)

1.聊聊redis缓存穿透问题

如何理解缓存穿透呢?就是当请求访问过来时 先去查询redis缓存,如果缓存中没有, 再去查询mysql数据库, 然后mysql数据库返回数据到redis缓存中, redis接收数据并把数据存储起来, 这样当下次请求过来时,服务端就直接查询redis缓存了并返回给客户端,不必再去查询mysql,缓解了数据库压力,并提高了效率 这是我们的正常情况对不对!

但但但但但但但是......有没有想过一个问题,如果是黑客恶意攻击,客户端发起的请求中的数据,我们缓存中不仅没有,就连我们的mysql中也没有! 这下完犊子了 这下客户端只要重复的发送这个请求,所有的请求会经过redis后然后再来请求我们的mysql,因为我们数据库中没有呀,所以查询不到,也没有数据往redis中存),这就是缓存穿透

那么如果是一个黑客恶意发起请求,mysql就有可能在长时间内持续承受大量的请求,mysql这时候心里很苦,很快就会撂挑子不干了,直接宕机,(接下来,整个系统宕机,然后你就抓紧删库跑路吧,(逃,

如果是大型项目的话,这个损失是很大的

那我们就要像羔羊一样任人宰割吗?NONONO,redis还有一个好兄弟,这个好兄弟叫作布隆过滤器

这个好兄弟可以存放大数据量,(偷偷告诉你,存放大数据量是他的优点,但是他也有缺点,就是查询到的结果不一定准确,0代表一定没有,1代表不一定有,布隆过滤器这位redis的好兄弟我这里就不介绍了,只介绍这位好兄弟如何仗义行侠帮助我们的redis

在中间加了这位好兄弟,那么当请求进来后,会首先经过我们的布隆过滤器,这个好兄弟先判断这个数据存不存在,若判断不存在直接丢弃请求,若这个数据存在再去进行redis查询,然后执行下一步,最后响应,有了这位好兄弟,我们就可以讲数据库中所有的查询条件,放入布隆过滤器中,所有的请求先交给这位好兄弟来处理(这位好兄弟是有那么一点不靠谱,但是大体上并不影响

其实还有一种解决方案是把查询到的空值的key缓存起来并设置过期时间,但是会有一种弊端,就是如何发起大量的请求,那岂不是要接收多少空值的key,都要存在redis中,redis是内存数据库,内存不要钱吗?而且遭到恶意攻击,能有多大内存和黑客刚呢?

具体场景具体用法:

  1. 如果空值的key少可以考虑缓存起来
  2. 如果空值的key多并且不重复,还是让布隆过滤器这位好兄弟来拔刀相助比较好

2.聊聊redis缓存雪崩问题

缓存雪崩可以这样理解,雪崩雪崩嘛!这些缓存就像雪一样发生了崩塌,缓存是存在于我们的redis这位好兄弟这里的,这位好兄弟平常管理着这些缓存,加入哪一天这兄弟不高兴了,撒手不干了,宕机),那岂不是这些缓存数据又没了,当请求来临时又要mysql兄弟处理了,mysql兄弟看到这么些请求过来淦它,心里直发怵啊!简直是瑟瑟发抖,造成了结果就是数据库崩溃,系统崩溃 这就是我们缓存雪崩,简单来说redis宕机了

解决方案也很简单,简单粗暴,一个不行来俩甚至更多,一节更比六节强,搭建redis集群然后交给hystrix来监控

3.聊聊缓存击穿问题

缓存击穿这个和缓存穿透字面上有点像,但是区别在于缓存穿透是数据中没有这个key,但是缓存击穿是数据中有这个key,并且我们要把这个key缓存到redis中,

比如淘宝双11,并不是所有的商品都要搞活动,只是一部分搞活动,那么这一部分商品在活动开始时,必然会有大量的用户去抢购,大量的请求),这时候如果我们的数据在mysql中,mysql必然不干了,mysql这位兄弟内存又要骂娘了,那么我们就需要redis来救场,提前把这些热点的key(需要搞活动的商品)缓存到redis中,当活动开始时直接去淦redis,没事redis扛得住,这样就解决了这个问题

但但但但但但是.......如果这个key突然在用户还没抢购完的时候,很妈离谱就过期了!那么完犊子,mysql又要骂娘了

这就是缓存击穿(热点key过期问题)

解决方案:

  1. 热点key竟然要妈离谱过期,我们在设置热点key时让这个bi永不过期就完事了,简单粗暴
  2. 互斥锁,当第一个查询数据库的请求发起时,给缓存中这个数据上锁,其他请求这个key等待,当第一个查询数据库打请求完成后解锁,其他请求直接从缓存中查