Redis--Redis集群、缓存穿透、缓存击穿、缓存雪崩

72 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情

👨‍🎓作者:Java学术趴

🏦仓库:GithubGitee

✏️博客:CSDN掘金InfoQ云+社区

💌公众号:Java学术趴

🚫特别声明:原创不易,未经授权不得转载或抄袭,如需转载可联系小编授权。

🙏版权声明:文章里的部分文字或者图片来自于互联网以及百度百科,如有侵权请尽快联系小编。微信搜索公众号Java学术趴联系小编。

☠️每日毒鸡汤:一件事你犹豫去不去做,那就是该立即动身做的。

1. Redis集群

1.1 为什么使用集群

当Redis容量不够,Redis该如何扩容?

当并发写操作时,Redis如何分摊?

另外,主从模式、薪火相传、主机宕机模式,导致ip地址发生变化,应用程序中配置了需要修改对应的主机地址、端口信息。

之前通过代理主机解决,但是 Redis3.0 之后提供了解决方案。就是 去中心化集群配置

1.2 集群的搭建方式

1.2.1 代理主机模式

  • 用户、订单、商品都对应的一个服务器的主从关系。
  • 代理主机 作为 Redis集群的入口,在该代理中判断分配给哪个主从服务器进行处理。
  • 存在问题:当代理主机宕机之后,整个集群就不能使用了。

1.2.2 无中心化集群

  • 没有指定的集群入口,可以从任何一个主从服务器当作是 Redis 集群的入口。
  • 每个主从服务器之间可以进行交互,不需要代码机器进行分配。
  • 当有一个主从服务器宕机的时候,不会影响到其他主从服务器的运行,Redis集群还可以使用。

1.3 什么是集群

  • Redis集群实现了对 Redis 的水平扩容,即启动 N 个 Redis 节点,将整个数据库分布存储在这N个节点中,每个节点存储总数数据的 1/N。
  • Redis集群通过分区来提供一定程度的可用性;即使集群中有一部分节点失效或者无法通讯,集群也可以继续处理命令请求。

1.4 集群优点

  • 实现扩容。
  • 分摊压力。
  • 无中心化配置。

1.5 Redis的不足

  • 多键操作是不被支持的。
  • 多键盘的Redis服务不被支持。lua脚本不被支持。

2. 使用会遇到的问题

2.1 缓存穿透

2.1.1 缓存穿透介绍

  • key对应的数据在数据源中不存在,每次针对此key的请求从缓存中获取不到,请求都会压到数据源,从而可能压垮数据源。比如一个不存在的用户id获取用户信息。不论缓存还是数据库都没有,若黑客利用此漏洞进行工具可能压垮数据库。

2.1.2 缓存穿透的解决方案

  • 对空值缓存 : 如果查询返回的数据为空(不管数据是否存在),我们仍然把这个空结果(null)进行缓存,设置空结果的过期时间会很短,最长不超过五分钟。
  • 设置可访问的名单(白名单) : 使用bitmaps类型定义一个可以访问的名单,名单id作为bitmaps的偏移量,每次访问和bitmaps里面的id进行比较,如果访问id不在bitmaps里面,进行拦截,不允许访问。
  • 采用布隆过滤器 : (布隆过滤器是 1970 年由布隆提出的),它实际上是一个很长的二进制向量(位图)和一系列随机映射函数(哈希函数)。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询效率都远远高于其他的算法,缺点是有一定的错误识别率和删除苦困难。
  • 进行实时监控 : 当发现Redis的命中率开始急剧下降时,需要排查访问对象和访问的数据,和运维人员配合,可以设置黑名单限制服务。

2.2 缓存击穿

2.2.1 缓存击穿介绍

  • key对应的数据存在,但在 Redis 中过期,此时如果有大量并发请求,这些请求发现缓存中的数据已经过期,此时就会直接从数据库中查询写入到Redis中,如果这个阶段存在大量的请求,那么可能会瞬间把数据库压垮。

9.2.2 解决方案

  • 预先设置热门数据 : 在 Redis 高峰访问之前,把一些热门数据提前存入到Redis里面,加大这些热门数据key的时长。比如一个热搜。
  • 实时调整 : 现场监控哪些数据热门,实时调整key过期时长。
  • 使用锁 :就是在缓存失效的时候(判断拿出来的值为空),不是立即去 load db。

2.3 缓存雪崩

2.3.1 缓存雪崩介绍

  • key对应的数据存在,但在 Redis 中过期,此时若有大量的并发请求过来,这些请求发现缓存过期,这个时候就会查询数据库重新写到 Redis 中,这个时候大并发请求可能会把数据库瞬间压垮。
  • 缓存失效雪崩时对底层系统的冲击力非常可拍。

缓存雪崩和缓存穿透的区别:缓存雪崩是针对的大量的key,缓存击穿是针对的某一个 key

2.3.2 解决缓存雪崩问题

  • 构建多级缓存架构 :nginx缓存 + redis缓存 + 其他缓存( ehcache 等)
  • 使用锁或者队列 : 用锁或者队列的方式保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。这种方式不适用于高并发情况。
  • 设置过期标志更新缓存 :记录缓存数据是否过期(设置提前量),如果过期回触发通知线程,被通知的线程去后台更新实际的 key 到缓存中。
  • 将缓存失效时间分散开:比如我们可以在原有的失效时间基础上增加一个随机值,比如:1~5分钟随机,这样每一个缓存的过期时间重复率会降低,就很难引发集体失效的事件。也就是每个key的失效事件设置为不一样的,在不同的时间更新ley,而不是在某个时间点更新所有的key。

Redis核心:单线程 + IO多路复用技术