本篇内容包括:Redis 主从架构、Redis 哨兵架构、Redis 集群架构 的介绍等内容~
文章目录
- 一、Redis 主从架构
- 1、Redis 主从架构
- 2、主从架构原理
- 二、Redis 哨兵模式
- 1、Redis 哨兵模式
- 2、Redis 哨兵模式工作过程
- 三、Redis 集群模式
- 1、Redis 集群模式
- 2、Redis 集群原理
一、Redis 主从架构
1、Redis 主从架构
主从复制模式就是,部署多台 Redis 节点,其中只有一台节点是主节点(Master),其他的节点都是从节点(Slave),也叫备份节点(Replica)。只有 Master 节点提供数据的事务性操作(增删改),Slave 节点只提供读操作。所有 Slave 节点的数据都是从 Master 节点同步过来的
Redis 主从架构样式图:
该图只是最简单的一种主从结构方式,所有的 Slave 节点都挂在 Master 节点上
- 优点: Slave 节点与 Master 节点的数据延迟较小;
- 缺点:如果 Slave 节点数量很多,Master 同步一次数据的耗时就很长。
还有一种主从结构就是 Master 下面只挂一个 Slave 节点,其他的 Slave 节点挂在这个 Slave 节点下面,这样,Master 节点每次只需要把数据同步给它下面的那一个 Slave 节点即可,后续 Slave 节点的数据同步由这个 Slave 节点完成。
- 优点:降低了 Master 节点做数据同步的压力
- 缺点:导致 Slave 节点与 Master 节点数据不一致的延迟更高。
2、主从架构原理
主从模式的核心就是 Master 节点与 Slave 节点之间的数据同步。需要注意的是,Redis 和大部分中间件的主从模式中的数据同步都是由 Slave 节点主动发起的,原因是主从模式中只有一个 Master 节点,剩余的全是 Slave 节点,如果由 Master 节点主动推送数据到各个 Slave 节点
- 首先,维护成本太大,Master 节点上要维护所有 Slave 的地址信息,而且在增加 Slave 节点的时候,也要同步维护到 Master 上,这样 Master 才能将数据同步到所有的 Slave 上面;
- 其次,Master 性能受影响,节点之间同步数据肯定要通过网络传输数据,由 Master 节点建立所有 Slave 节点的连接会对 Master 的性能产生较大影响。
而由 Slave 发起数据同步则避免了上述问题,只需在每个 Slave 中维护一个 Master 的地址即可。
- Slave 发送 sync 命令到 Master
- Master 收到 sync 之后,执行bgsave,生成 RDB 全量文件
- Master 把 Slave 的写命令记录到缓存
- bgsave 执行完毕之后,发送 RDB 文件到 Slave,Slave 执行
- Master 发送缓存中的写命令到 Slave,Slave 执行

在 redis2.8 版本之后已经使用 psync 来替代 sync 了,原因是 sync 命令非常消耗系统资源,而 psync 的效率更高。
二、Redis 哨兵模式
1、Redis 哨兵模式
基于主从方案的缺点还是很明显的,假设 Master 宕机,那么就不能写入数据,那么 Slave 也就失去了作用,整个架构就不可用了,除非你手动切换,主要原因就是因为没有自动故障转移机制。
而哨兵(sentinel)的功能比单纯的主从架构全面的多了,哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它独立运行。其原理是哨兵通过发送命令,等待 Redis 服务器响应,从而监控运行的多个 Redis 实例。因此哨兵模式具备了自动故障转移、集群监控、消息通知等功能。

2、Redis 哨兵模式工作过程
哨兵可以同时监视多个主从服务器,并且在被监视的 Master 下线时,自动将某个 Slave 提升为 Master,然后由新的 Master 继续接收命令。整个过程如下:
- 初始化 sentinel,将普通的 redis 代码替换成 sentinel 专用代码
- 初始化 Masters 字典和服务器信息,服务器信息主要保存 ip:port,并记录实例的地址和 ID
- 创建和 Master 的两个连接,命令连接和订阅连接,并且订阅 sentinel:hello 频道
- 每隔 10 秒向 Master 发送 info 命令,获取 Master 和它下面所有 Slave 的当前信息
- 当发现 Master 有新的 Slave 之后,sentinel 和新的 Slave同样建立两个连接,同时每个10秒发送 info 命令,更新 Master 信息
- sentinel 每隔1秒向所有服务器发送 ping 命令,如果某台服务器在配置的响应时间内连续返回无效回复,将会被标记为下线状态
- 选举出领头 sentinel,领头 sentinel 需要半数以上的 sentinel 同意
- 领 头sentinel 从已下线的的 Master 所有 Slave 中挑选一个,将其转换为 Master
- 让所有的 Slave 改为从新的 Master 复制数据
- 将原来的 Master 设置为新的 Master 的从服务器,当原来 Master 重新回复连接时,就变成了新 Master 的从服务器
其中,sentinel 会每隔 1 秒向所有实例(包括主从服务器和其他sentinel)发送 ping 命令,并且根据回复判断是否已经下线,这种方式叫做主观下线。当判断为主观下线时,就会向其他监视的 sentinel 询问,如果超过半数的投票认为已经是下线状态,则会标记为客观下线状态,同时触发故障转移。
三、Redis 集群模式
1、Redis 集群模式
如果说依靠哨兵可以实现redis的高可用,如果还想在支持高并发同时容纳海量的数据,那就需要 redis 集群。redis 集群是 redis 提供的分布式数据存储方案,集群通过数据分片sharding来进行数据的共享,同时提供复制和故障转移的功能。
2、Redis 集群原理
# 节点:一个 redis 集群由多个节点 node 组成,而多个 node 之间通过 cluster meet 命令来进行连接,节点的握手过程:

- 节点 A 收到客户端的 cluster meet 命令
- 节点 A 根据收到的 IP 地址和端口号,向 B 发送一条 meet 消息
- 节点 B 收到 meet 消息返回 pong
- 节点 A 知道 B 收到了 meet 消息,返回一条 ping 消息,握手成功
- 最后,节点 A 将会通过 gossip 协议把节点 B 的信息传播给集群中的其他节点,其他节点也将和 B 进行握手
# 槽 slot:redis 通过集群分片的形式来保存数据,整个集群数据库被分为 16384 个 slot,集群中的每个节点可以处理 0-16383 个slot,当数据库 16384 个 slot 都有节点在处理时,集群处于上线状态,反之只要有一个 slot 没有得到处理都会处理下线状态。通过 cluster addslots 命令可以将 slot 指派给对应节点处理。
slot 是一个位数组,数组的长度是 16384/8=2048,而数组的每一位用 1 表示被节点处理,0 表示不处理,如图所示的话表示 A 节点处理 0-7 的slot。
当客户端向节点发送命令,如果刚好找到 slot 属于当前节点,那么节点就执行命令,反之,则会返回一个MOVED命令到客户端指引客户端转向正确的节点。(MOVED过程是自动的)
如果增加或者移出节点,对于 slot 的重新分配也是非常方便的,Redis 提供了工具帮助实现 slot 的迁移,整个过程是完全在线的,不需要停止服务。
# 故障转移:
如果节点 A 向节点 B 发送 ping 消息,节点 B 没有在规定的时间内响应 pong,那么节点 A 会标记节点 B 为 pfail 疑似下线状态,同时把 B 的状态通过消息的形式发送给其他节点,如果超过半数以上的节点都标记 B 为 pfail 状态,B 就会被标记为 fail 下线状态,此时将会发生故障转移,优先从复制数据较多的从节点选择一个成为主节点,并且接管下线节点的 slot,整个过程和哨兵非常类似,都是基于 Raft 协议做选举。