Redis--Redis 集群、缓存穿透、缓存击穿、缓存雪崩
👨🎓作者:Java 学术趴
💌公众号: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 多路复用技术
版权声明: 本文为 InfoQ 作者【Java学术趴】的原创文章。
原文链接:【http://xie.infoq.cn/article/7e7937494fd013cbed9471d3c】。文章转载请联系作者。
评论