Redis缓存相关问题

Redis最常见的应用场景就是作为缓存,本文主要介绍Redis作为缓存过程中可能遇到的若干问题,包括缓存穿透、击穿、雪崩和一致性等问题。

缓存穿透

问题来源

使用Redis作为缓存的目的就是:将经常使用的数据放到Redis中,这样在使用的时候就可以直接从缓存中取,无需访问数据库,大大提高数据读取效率。

缓存穿透是指:大量请求的key没有命中缓存,导致请求直接到了数据库上。比如,某个黑客故意制造缓存中不存在的key发起大量请求,很可能就导致DB挂掉了。

解决方案

  1. 接口校验

    这是最基本方案,直接在接口层增加校验,比如 用户鉴权校验,id校验(不能小于0) 邮箱格式校验等等,将不合法请求拦截。

  2. 缓存无效key

    如果缓存和数据库中都查不到某个key,就写一个到Redis中,并设置过期时间。这种方式可以解决请求的 key 变化不频繁的情况,如果黑客恶意攻击,每次构建不同的请求 key,会导致 Redis 中缓存大量无效的 key 。

  3. 布隆过滤器

    布隆过滤器是一个非常神奇的数据结构,通过它我们可以非常方便地判断一个给定数据是否存在于海量数据中。我们需要的就是判断 key 是否合法,有没有感觉布隆过滤器就是我们想要找的那个“人”。

    具体是这样做的:把所有可能存在的请求的值都存放在布隆过滤器中,当用户请求过来,先判断用户发来的请求的值是否存在于布隆过滤器中。不存在的话,直接返回请求参数错误信息给客户端,存在的话才会走下面的流程。

缓存击穿

问题来源

缓存击穿是指:一些设置过期时间的key在过期后的某个时间点,突然被超高并发访问,这些请求发现缓存过期后,同时向DB发起请求。

解决方案

  1. **永不过期:**设置热点数据永不过期;
  2. **mutex互斥锁:**只将一个请求发送到数据库,拿到数据并回设缓存后,解除锁;
  3. 接口限流与熔断,降级。重要的接口一定要做好限流策略,防止用户恶意刷接口,同时要降级准备,当接口中的某些服务不可用时候,进行熔断,失败快速返回机制。 (这个不太懂)

缓存雪崩

问题来源

缓存雪崩指: 缓存在同一时间大面积的失效,后面的请求都直接落到了数据库上,造成数据库短时间内承受大量请求。 可能出现在两个场景:

  1. 系统的缓存模块出了问题比如宕机导致不可用。造成系统的所有访问,都要走数据库。
  2. 有一些被大量访问数据(热点缓存)在某一时刻大面积失效,导致对应的请求直接落到了数据库上。

和缓存击穿的区别在于, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

解决方案

  • 针对 Redis 服务不可用的情况
    • 采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。
    • 限流,避免同时处理大量的请求。
  • 针对热点缓存失效的情况
    • 设置不同的失效时间比如随机设置缓存的失效时间。
    • 缓存永不失效。

数据库与缓存一致性

将Redis作为缓存使用时,读数据一般不会出现问题,向数据库写数据时就会出现一致性问题。我们是先向写数据库再写缓存?还是写些缓存后写数据库?无论哪种方式,如果第一步执行成功,第二步执行失败都会导致缓存与数据库数据不一致。

Cache Aside Pattern 旁路缓存模式

Cache Aside Pattern是最常用的一种缓存更新模式,其设定如下图所示:

当然,这种模式下也可能会出现更新数据库成功,删除缓存失败的场景,导致后续从缓存中读取的都是旧数据。解决方案有三种:
  1. 缩短过期时间:指标不治本,短时间内读取的还是旧数据。

  2. 同步重试

  3. 异步重试

总结

看到这里你可能会想,这些方案还是不够完美,我就想让缓存和数据库「强一致」,到底能不能做到呢?

其实很难。

要想做到强一致,最常见的方案是 2PC、3PC、Paxos、Raft 这类一致性协议,但它们的性能往往比较差,而且这些方案也比较复杂,还要考虑各种容错问题。

相反,这时我们换个角度思考一下,我们引入缓存的目的是什么?

没错,性能

一旦我们决定使用缓存,那必然要面临一致性问题。性能和一致性就像天平的两端,无法做到都满足要求。

如果为了短时间的不一致性问题,选择让系统设计变得更加复杂的话,完全没必要。

参考资料

  1. https://pdai.tech/md/db/nosql-redis/db-redis-x-cache.html
  2. https://javaguide.cn/database/redis/redis-questions-01
  3. https://mp.weixin.qq.com/s?__biz=MzIyOTYxNDI5OA==&mid=2247487312&idx=1&sn=fa19566f5729d6598155b5c676eee62d&chksm=e8beb8e5dfc931f3e35655da9da0b61c79f2843101c130cf38996446975014f958a6481aacf1&scene=178&cur_album_id=1699766580538032128#rd
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021-2022 Yin Peng
  • 引擎: Hexo   |  主题:修改自 Ayer
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信