Redis(1):四种模式(单机、哨兵、集群、主从复制)原理
学习自:redis的4种模式,单机,哨兵、主从复制、集群_redis单机和集群_本郡主是喵的博客-CSDN博客
Redis四种部署模式(原理、优缺点及解决方案)_redis高可用方案以及优缺点_少年做自己的英雄的博客-CSDN博客
下一节:Redis(2):四种模式(单机、哨兵、集群、主从复制)部署
为什么redis被称为redis服务器?
因为redis在运行时是被注册为一个进程(服务),我们将其称为redis服务器。
1、单机模式
安装redis,启动服务后,默认是单机模式。
特点:只有一个redis服务器(主服务器),但哨兵模式默认开启(只是挂掉后,没有能选举的)。
redis将数据存储于单个节点上,这个节点包括一个Redis进程和一个持久化存储。单机模式非常适合小型应用程序或者开发和测试环境,因为它提供了一个简单的方法来存储和检索数据,同时具有低延迟和高性能。
缺点
- 单点宕机会引起服务的灾难、数据丢失;
- 单点服务器内存瓶颈,无法无限纵向扩容
2、主从模式
主从模式在单机模式的基础上增加了数据备份的功能。在主从模式中,redis节点被分为主节点和从节点。主节点负责处理所有写操作(也可以读),从节点则复制(同步)主节点的数据,并负责处理读操作(只能读)。
优点
提高了可靠性和可扩展性,如果主节点故障,可以用从节点来恢复数据,将从节点手动升级为主节点继续服务。
缺点
从节点不能写,如果主节点挂掉则整个服务失去写的能力,仅具备读操作,需要运维手动升级,在此过程中会出现请求失败数据丢失。
解决方案
升级为哨兵模式,可以将slave自动升级为master
2.1、主从复制
从master复制数据到slave,数据复制是单向进行的。
每台服务器默认情况下都是master,如果要变成slave需要在配置文件中单独配置,才会从默认的master转变为slave。一个master可以有0或多个slave,而每个slave只能有一个master。
2.1.1、复制原理
- s第一次连接m,执行一次全量复制;
- 全量复制数据量过大时,会造成很大的网络开销;
- 增量复制用于主从复制中因网络原因造成的数据丢失场景,当s再次连接上m,且该m就是原来的m,如果条件允许,m会补发数据给s,补发量比较少,避免全量复制的开销(最终是否复制由offset和buffer决定)
- 如果s再次连上的是新m,那么进行的就是全量复制
- 早期redis只有全量复制,增量复制是2.8版本以后提供的,是对全量复制的优化
2.1.1.1、全量复制
- s给m发送一个sync同步命令
- m通过bgsave命令fork子进程,持久化生成RDB文件
- m通过网络将RDB文件传给s
- s将清空老数据,载入新的RDB文件,此时s阻塞,无法响应客户端,专心复制
2.1.1.2、增量复制
- 主从节点各自维护自己的复制偏移量offset,当m写入时,offset=offset+命令字节长度;s收到m也会增加自己的offset,并同步给m。m同时维护自己和s的offset,以此判断主从节点数据是否一致;
- m将指令记录在本地buffer,异步将buffer同步给s;
- 若网络不好,同步速度慢了,buffer满了就会从头开始覆盖前面的内容,此时不能增量复制,必须全量复制
2.2、读写分离
为什么将读放在s,写放在m?
因为读操作占绝大多数,这样做可以减缓服务器压力;同时一些执行耗时比较久的操作也可以放在一台s完成,例如keys、sort。
至于什么时间连m写,什么时间从s读,由客户端决定
最低配置
一主二从,当m宕机后,其中一个s升级为m,还能剩一个s。
主从模式是实现哨兵和集群的基础。
3、哨兵模式(Sentinel,2.8版本后)
在主从模式的基础上,添加了故障检测和自动故障转移功能。在哨兵模式下,一个或多个哨兵进程监视redis节点的运行状态。如果主节点故障,哨兵会检测到该情况并自动将其中一个从节点提升为新的主节点。这一过程是自动的,不需要人为干预。
哨兵模式提高了redis集群的可靠性,确保即使主节点发生故障,Redis服务也能继续运行。
如果哨兵挂了怎么办?哨兵一般是一个集群,一般由3-5个节点组成,即使个别节点挂了,集群还能正常运行。
优点
- 可以在m挂掉后重新选举产生新的m
缺点
- m挂掉了,切换新的m会造成未来得及主从同步的数据丢失
- 大数据高并发,单个m内存仍存在上限
- 主从全量同步仍要耗费大量时间
- 单个redis只能利用CPU单个核心,难以应对海量数据
解决方案
- 集群
3.1、一个m挂掉后整个系统的变化
客户端连接redis时,会首先连接sentinel(哨兵,下文简写为sen),通过sen查询m地址,再连接m进行数据交互。当m挂掉,客户端重新跟sen要m地址,连接新的m。
上图中,m挂掉,原先的主从复制断开,客户端和m也断开,之后一个s成为新的m,和其余的s进行新的主从复制。客户端通过新m继续交互,sen持续监控已经挂掉的旧m,一旦旧m恢复,集群变为下图,旧m成为新s,从新m建立主从复制关系。
要点
- 一个sen或sen集群可以管理多个主从redis,如果只有一个redis,那么sen将无意义
- m挂掉,sen在s中选举一个升级为新m,并修改配置文件
- 挂了的m恢复后,只能当s,跟新选举的m主从复制
- sen也会挂,所以sen一般是一个集群
- 每个sen定期检测redis数据节点、其他sen节点是否可达
- 对于节点的故障由多个sen节点共同判断,防止误判
- redis主从复制为异步,m挂掉,s会丢失一部分信息,sen不能保证信息完全不丢失,但尽量减少
- Sentinel.slave_for可以从连接池内采用轮询方案拿出一个s地址,实现负载均衡
3.2、定时监控
- 每1s,每个sen会向s、m、sen发送ping做一次心跳检测,来测试是否可达,实现对每个节点的监控;
- 每2s,每个sen会与其他sen通信,可以发现新sen节点,并与其他sen交换对m的判断信息,方便故障转移和选举
- 每10s,每个sen会向s、m发送info命令获取最近的拓扑结构,可以感知新加入或故障转移的redis数据节点。
3.3、主观下线和客观下线
主观下线
当sen节点ping其他节点,超时,sen就会对该节点做失败判定。
主观下线是当前sen的一家之言,存在误判。
客观下线
当sen主观下线的节点为m,sen会向其他sen询问对该m的判断,当大多数sen都对m的下线做了同意判断,那这个判断就是客观的。
3.4、Sentinel领导者选举
sen对m做了客观下线,但还不能立刻进行故障转移,因此故障转移只需要一个sen来完成,因此在sen集群中要选出一个leader进行故障转移。
redis使用了raft算法来实现领导者选举:
- 每个在线的sen都有资格成为领导者,它要求其他节点来投自己一票
- 先收到谁的要求就给谁投票,但不能给自己投
- 先拿到大多数票(n/2+1)的当选领导者
3.4、故障转移
sen领导者负责此次故障转移:
- 排除主观下线的s;
- 选择优先级高的s,如果没有再进行3;
- 选择复制偏移量最大的s(复制的最完整),如果没有再进行4;
- 选择runid最小的s。
4、集群模式(3.0版本后)
集群模式是在多个Redis节点之间分配数据,提供更高的可扩展性和容错能力。
在集群模式中,数据被分配到多个Redis节点上,每个节点处理自己的数据。当一个节点失效时,集群会自动将该节点的数据迁移到其他节点上。集群模式在redis大规模部署中很有用,因为它可以轻松扩展和缩小redis集群,而不会影响到整个系统的性能和可靠性。
集群模式真正实现了redis高可用,有很多实现方式,目前最常用的Redis Cluster(以下简称为RC)是Redis的亲儿子,是Redis作者自己提供的Redis集群化方案,从Redis3.0版本开始正式提供。
集群由多个Redis主从组成,每个主从代表一个节点,每个节点负责一部分数据,它们之间通过一种特殊的二进制协议交换集群信息。
Redis Cluster将所有数据分片,分成16384个槽位,RC将Key值用crc16算法进行hash,然后用除留余数对模除16384得到具体槽位,每个节点负责其中一部分槽位。
当客户端连接集群,会得到一部分集群的槽位匹配信息,当客户端要查找Key,可以直接定位到目标节点。
Cluster去中心化,由多个节点组成,客户端连接时可以只用一个节点的地址,其余节点可以通过该节点自动发现,但如果该节点挂掉,就必须手动更换地址,因此连接多个地址的安全性更高。
容错
RC拥有类似哨兵功能,每个节点仍需要设置若干s,当m故障时,集群可将s升级为m。
RC去中心化,当集群内某个节点不可用时,一个节点认为失联不代表所有节点认为失联(主观下线与客观下线),集群要进行一次商议,只有大多数节点都认为它失联,才会认为其需要主从切换来容错。
动态扩容
假设原先集群中有3个节点,一共3000条数据,可能1-1000在第一个节点,1001-2000在第二个节点,2001-3000在第三个节点。
当新节点加入集群,需要手动将槽和数据迁移到新节点,可以使用redis-trib工具或手动命令迁移。
大致流程:
- 从源节点获取内容
- 存到目标节点
- 删除源节点内容
优点
- 无中心架构,支持动态扩容
- Cluster自动具备哨兵监控和故障转移(主从切换)能力
- 客户端连接集群内地址可以自动发现
- 高性能、高可用,有效解决了Redis分布式需求
缺点
- 运维复杂
- 只能用0号数据库
五、常见问题
1、Sentinel节点为什么是至少三个且奇数个?
首先必须是集群,所以不能是1个。而选举过程要大多数同意才行(即最少一半+1个),而奇数个节点在同样选举条件上可以节省一台机器。
比如一共5台,有3台同意了就行;而4台,大多数同意也要3台。
2、Redis集群节点数为什么至少是6个?
6个包含一主一从,如果每个节点一主二从则需要9个
最少3个节点,是因为容错能力相同情况下,奇数节点更节省资源(3个节点的集群允许一个节点宕机;而4个节点的集群也允许一个节点宕机)
3、为什么Redis Cluster槽位设计成16384个?
2^14=16384,当槽位再扩就是32768、65536,此时每一次ping都要将槽位作为心跳包,信息太大,占用带宽
由于集群节点越多,心跳包携带的数据就越多。当节点超过1000,会导致网络拥堵。因此Redis作者不建议Redis Cluster节点数量超过1000,那么16384槽位也足够用