传送门
SpringMVC的源码解析(精品)
Spring6的源码解析(精品)
SpringBoot3框架(精品)
MyBatis框架(精品)
MyBatis-Plus
SpringDataJPA
SpringCloudNetflix
SpringCloudAlibaba(精品)
Shiro
SpringSecurity
java的LOG日志框架
Activiti(敬请期待)
JDK8新特性
JDK9新特性
JDK10新特性
JDK11新特性
JDK12新特性
JDK13新特性
JDK14新特性
JDK15新特性
JDK16新特性
JDK17新特性
JDK18新特性
JDK19新特性
JDK20新特性
JDK21新特性
其他技术文章传送门入口
前言
Redis的集群非常重要,基本小项目都是单Redis,而大一点的项目确实需要集群了。学中间件,集群必须掌握。如果读者已经熟悉基本的集群模式,请直接看第三章节:Redis集群架构(最佳),为本文核心内容。
下面文章不定期更新:
Redis入门篇(精品)
Redis命令篇(精品)
Redis高级篇(精品)
Redis集群篇(精品)
Redis面试篇(精品)
Redis 集群是 Redis 提供的一种分布式解决方案,旨在提供高可用性和横向扩展能力。下面是关于 Redis 集群的一些关键信息和特性:
概述
Redis 集群使用分区(sharding)来水平拆分数据,将数据分散存储在多个 Redis 节点上,从而允许在多个节点上进行数据操作,并通过内部协调机制实现数据的高可用性和负载均衡。
主要特性
1、分区(Sharding):
- Redis 集群将数据划分为 16384 个哈希槽(hash slots),每个节点负责其中一部分哈希槽。这样可以将数据均匀地分布在集群中的各个节点上。
2、自动数据复制:
- Redis 集群使用主从复制(master-slave replication)来确保数据的高可用性。每个主节点都有若干个从节点,数据会被复制到这些从节点上,从而在主节点故障时,能够快速切换到从节点提供服务。
3、节点间通信:
- Redis 集群使用集群总线(cluster bus)来进行节点间的通信,用于集群管理、故障检测和故障转移等功能。
4、客户端路由:
- 客户端与 Redis 集群的交互由客户端库负责,客户端库会根据哈希槽映射表将命令路由到正确的节点上。每个节点负责管理一部分数据,客户端需要知道哪个节点管理哪些哈希槽。
5、故障检测与自动故障转移:
- Redis 集群能够自动检测节点的故障,并通过重新选举主节点或者从已有的从节点晋升为新的主节点来实现自动故障转移。
6、动态扩展和缩减:
- 可以动态地向 Redis 集群中添加节点(增加槽位的分布)或者移除节点(重新分配槽位),以满足不同规模和负载的需求。
使用场景
- 大规模数据存储和处理:适用于需要处理大量数据或高并发读写操作的场景,如缓存、实时计算等。
- 高可用性需求:对于需要保证服务稳定性和故障恢复能力的应用,Redis 集群提供了自动故障转移和数据备份功能。
- 横向扩展:当单个 Redis 实例无法满足性能需求时,可以通过添加节点来扩展集群的处理能力,而无需修改应用程序。
注意事项
- 配置和部署:Redis 集群的配置和部署相对复杂,需要正确设置节点间的通信和数据复制机制。
- 数据分布:应用程序需要意识到数据被分散存储在多个节点上,需要通过正确的客户端路由来访问数据。
- 事务操作限制:由于 Redis 集群的分区特性,不同键可能存储在不同节点上,因此事务操作不能跨节点进行。
Redis 集群通过分布式架构和自动化管理功能,提供了高性能、高可用性的数据存储和处理解决方案,适合于大规模和高并发的应用场景。
一、Redis主从复制
指定一台Redis服务器为主节点master/leader,复制到其他的Redis服务器,其他的称为从节点slave/follower;数据的复制是单向的,只能主导从,master以写为主,slave以读为主。默认情况下都是主,需要配置,一个主有多个从,但一个从只能有一个主。
环境配置:
只配置从库,不配置主库(因为默认就是主),截图是用命令配置从机的,重启后配置会丢失,又会变成主机,所以永久修改的办法是修改配置问题(修改4个地方,看截图)。主机宕机后,从机在没有开启哨兵模式的时候,一直是从机,当主机恢复后,任然保持不变,主机写从机拷贝后可以读;从机宕机后,非命令行配置的,重启后任然是从机,并且马上就把主机的东西复制了,然后就可以读了。
复制原理:
全量复制,当从机第一次连接主机时,全量复制主机的内容;
增量复制,主机写一些内容进去,从机就复制一些内容;
手动谋朝篡位:
一般一个M带一个S1和一个S2,但是也可以一个M带一个S1,S1又带了S2(本质上S1和S2还是从不能写数据,只是M的从机数量由2变成1了,S1有了从机 数量)。
当一个主机宕机了,从机可以使用slaveof no one 手动变成主机,不过其他节点也得手动连接到这个心主机。
概念
环境配置
一主二从
配置从机(slaveof 127.0.0.1 6379),只能主机写从机不能写
复制原理截图
二、Redis哨兵模式(自动选举老大的模式)
配置哨兵,主机和从机每个都有一个哨兵来监控,如果Master宕机了,监控主机的哨兵不会马上投票,要等等,当 其他哨兵也发现master宕机了,发现哨兵的数量达到一定值时,通过发布订阅,就会从从机中投票选择一个票数高的服务器当做master(具体概念看截图);当之前宕机的主机重新恢复后,也只能当之前选举出来做master的机器的从机了(自动完成)(自动版谋朝篡位)。
优点:主从可以切换,故障可以转移,高可用,是主从模式的升级,更加健壮
缺点:Redis不好在线扩容,集群一旦到达上限,扩容非常麻烦;实现哨兵模式的配置其实非常麻烦,里面有很多选择。master单节点不是集群,挂了以后有时候需要几秒才能恢复,客户端会有不少报错。还有就是虽然理论10万并发,但是还是单master节点,其他两个节点主要用来备份,不是所谓的真集群,设置内存最好不要超过10GB大小,如果数据量太大,启动恢复或者主从同步效率都会很差。而且超大量的数据,这种模式是搞不定的。
注意:客户端访问的先是访问 哨兵集群,然后由哨兵集群告诉客户端访问哪一个redis节点,哨兵也是redis实例。哨兵集群最清楚哪个是master,然后客户端第二次才去访问真正的redis主节点。
概念
哨兵模式
多哨兵模式
配置哨兵模式
哨兵模式全部配置1
哨兵模式全部配置2
哨兵模式全部配置3
三、Redis集群架构(最佳)
最佳,也会出现master挂了几秒才能恢复的这种情况。比如90GB的内存,这个集群图,三个master各分30GB,当第一个挂了,访问到第一个的时候,肯定会有报错的情况,但是如果数据是其他两台集群上的,那么就可以正常访问,这个是分片特性。所以比哨兵还是好太多了,而且方便扩展,配置简单。
在 Redis 集群架构中,配置主要分为以下几个步骤:创建和启动 Redis 节点、设置集群模式、添加节点并进行握手、检查集群状态等。下面是一个简单的示例,演示如何使用 Redis 的官方工具 redis-trib.rb 来配置 Redis 集群。
准备工作
首先,确保你已经安装了 Redis,并且在多台服务器上准备了 Redis 实例。假设我们有 6 台服务器(每台服务器上运行一个 Redis 实例,3主3从),IP 分别为:
- 192.168.1.10
- 192.168.1.11
- 192.168.1.12
- 192.168.1.13
- 192.168.1.14
- 192.168.1.15
步骤
1、在每个服务器上启动 Redis 实例
假设 Redis 已经正确安装和配置,可以通过以下方式启动 Redis 实例。假设 Redis 配置文件路径为 /etc/redis/redis.conf,可以在每台服务器上执行以下命令:
redis-server /etc/redis/redis.conf
2、创建 Redis 集群
Redis 提供了 redis-trib.rb 脚本来管理 Redis 集群的创建和维护。以下是一个示例的步骤和命令:
- 连接到其中一台服务器,假设为 192.168.1.10:
cd /path/to/redis/src # 进入 redis-trib.rb 所在的目录
./redis-trib.rb create --replicas 1 192.168.1.10:6379 192.168.1.11:6379 192.168.1.12:6379 192.168.1.13:6379 192.168.1.14:6379 192.168.1.15:6379
- –replicas 1 参数指定每个主节点有一个从节点。如果是3主6从9台机器,这里可以 --replicas 2 参数指定每个主节点有两个从节点。
- 在执行命令后,redis-trib.rb 会询问你是否将节点分配到集群,确认后开始创建 Redis 集群。
3、验证集群状态
创建完成后,可以通过 redis-cli 连接到任何一个 Redis 节点,执行 cluster nodes 命令来查看集群的节点状态:
redis-cli -h 192.168.1.10 -p 6379
192.168.1.10:6379> cluster nodes
输出应该显示所有节点的状态和连接信息。
注意事项
- 节点握手: 在添加新节点或重新平衡集群时,新节点需要与集群中的其他节点握手。这由 redis-trib.rb 自动处理。
- 故障转移: 当主节点出现故障时,Redis 集群会自动将一个从节点提升为新的主节点,以保持高可用性。
- 监控与维护: 需要定期监控 Redis 集群的状态和性能,并在必要时进行扩展或修复。
这些是配置 Redis 集群的基本步骤和示例。根据实际情况,你可能需要调整 IP 地址、端口号以及其他参数,以适应你的环境和需求。
四、Redis缓存穿透和雪崩(面试高频)
1、缓存穿透:(查不到,量太大)【缓存和数据库都没有】
用户请求,redis缓存没有就去持久层查询,当用户很多的时候,缓存都没有命中,于是都去请求持久层了,会给持久层很大的压力,这时候就出现了缓存穿透。
解决方案:布隆过滤器(是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合就丢弃,从而避免了对底层存储 查询压力,其实就是过滤器),缓存空对象(查不到的返回空值,缓存这些空对象浪费空间,哪怕设置过期,又有一段时间数据不一致,不太好)
2、缓存击穿:(缓存过期,空档期量太大)【缓存没有,数据库有】
redis缓存的key过期瞬间,如果有海量并发请求,比如56秒失效,56.1秒恢复key,这0.1秒内有海量并发请求,会像子弹一样,在 一点瞬间击穿,海量并发就去访问数据库了,会让数据库瞬间压力过大(关晓彤和鹿晗官宣恋爱,微博服务器宕机,就是海量并发都在查这条消息,是典型的缓存击穿)
解决方案:设置热点数据永不过期,加互斥锁(原来海量并发会通过很多线程去访问数据库,现在只保留一个线程访问数据库,其余线程等待)
3、缓存雪崩:
比如双11活动,抢购一波商品,这批商品放在缓存中,如果缓存一小时后过期,这个时候这批商品访问都会落到数据库,会导致数据库也蹦的情况出现(一般这种不是最致命的,最致命的是Redis断电或者其他原因集群宕机)
解决方案:redis高可用(搭建健壮集群);限流降级(比如双11停掉一些服务,保证主要服务可用,比如当天退款,提示不能退款);数据预热(根据不同产品设置不同的key过期时间,比如双11就在凌晨三点以后,比如小米手机,在10点抢购,就根据不同产品灵活设置不同的过期时间)
穿透:
缓存穿透:缓存和数据库中都没有的数据,可用户还是源源不断的发起请求,导致每次请求都会到数据库,从而压垮数据库。
比如客户查询一个根本不存在的东西,首先从Redis中查不到,然后会去数据库中查询,数据库中也查询不到,那么就不会将数据放入到缓存中,后面如果还有类似源源不断的请求,最后都会压到数据库来处理,从而给数据库造成巨大的压力。
(个人总结:null不缓存导致redis是个摆设透明了,穿透 到数据库去查了)【缓存和数据库都没有】
解决办法
①、业务层校验
用户发过来的请求,根据请求参数进行校验,对于明显错误的参数,直接拦截返回。
比如,请求参数为主键自增id,那么对于请求小于0的id参数,明显不符合,可以直接返回错误请求。
②、不存在数据设置短过期时间
对于某个查询为空的数据,可以将这个空结果进行Redis缓存,但是设置很短的过期时间,比如30s,可以根据实际业务设定。注意一定不要影响正常业务。
③、布隆过滤器
关于布隆过滤器,后面会详细介绍。布隆过滤器是一种数据结构,利用极小的内存,可以判断大量的数据“一定不存在或者可能存在”。
对于缓存击穿,我们可以将查询的数据条件都哈希到一个足够大的布隆过滤器中,用户发送的请求会先被布隆过滤器拦截,一定不存在的数据就直接拦截返回了,从而避免下一步对数据库的压力。
击穿:
缓存击穿:Redis中一个热点key在失效的同时,大量的请求过来,从而会全部到达数据库,压垮数据库。
这里要注意的是这是某一个热点key过期失效,和后面介绍缓存雪崩是有区别的。比如淘宝双十一,对于某个特价热门的商品信息,缓存在Redis中,刚好0点,这个商品信息在Redis中过期查不到了,这时候大量的用户又同时正好访问这个商品,就会造成大量的请求同时到达数据库。
(个人总结:就像屏幕上凿开了个洞,单个热点key,单点击穿,毕竟穿透是大面积的,击穿是小面积的聚集的力量。)【缓存没有,数据库有】
解决办法
①、设置热点数据永不过期
对于某个需要频繁获取的信息,缓存在Redis中,并设置其永不过期。当然这种方式比较粗暴,对于某些业务场景是不适合的。
②、定时更新
比如这个热点数据的过期时间是1h,那么每到59minutes时,通过定时任务去更新这个热点key,并重新设置其过期时间。
③、互斥锁
这是解决缓存穿透比较常用的方法。
互斥锁简单来说就是在Redis中根据key获得的value值为空时,先锁上,然后从数据库加载,加载完毕,释放锁。若其他线程也在请求该key时,发现获取锁失败,则睡眠一段时间(比如100ms)后重试。
雪崩:
缓存雪崩:Redis中缓存的数据大面积同时失效,或者Redis宕机,从而会导致大量请求直接到数据库,压垮数据库。
对于一个业务系统,如果Redis宕机或大面积的key同时过期,会导致大量请求同时打到数据库,这是灾难性的问题。
(个人总结:这是整个屏幕都打的稀巴烂,多个热点key,或者宕机了,数据库拖死可能整个微服务都崩溃了。雪崩呀。)
【缓存没有,数据库有】
解决办法
①、设置有效期均匀分布(防止大量数据在同一时间过期)
避免缓存设置相近的有效期,我们可以在设置有效期时增加随机值;
或者统一规划有效期,使得过期时间均匀分布。
②、数据预热
对于即将来临的大量请求,我们可以提前走一遍系统,将数据提前缓存在Redis中,并设置不同的过期时间。
③、保证Redis服务高可用
前面我们介绍过Redis的哨兵模式和集群模式,为防止Redis集群单节点故障,可以通过这两种模式实现高可用。
分布式锁
https://maimai.cn/article/detail?fid=1531234921&efid=n30pYC_ME4DWwS2G-53Brw&use_rn=1