文章目录
- [一. 什么是主从复制?](#一. 什么是主从复制?)
- [二. Redis的主从复制](#二. Redis的主从复制)
-
- [1. 修改主节点配置文件](#1. 修改主节点配置文件)
- [2. 复制主节点配置文件并修改](#2. 复制主节点配置文件并修改)
- [3. 主从复制参数简单介绍](#3. 主从复制参数简单介绍)
- [4. 特点](#4. 特点)
- [5. 拓扑结构](#5. 拓扑结构)
-
- [(1) 一主一从拓扑](#(1) 一主一从拓扑)
- [(2) 一主多从拓扑](#(2) 一主多从拓扑)
- [(3) 树形拓扑](#(3) 树形拓扑)
- [6. psync 主从复制命令](#6. psync 主从复制命令)
- [7. 复制的执行流程](#7. 复制的执行流程)
-
- [(1) 主从复制总执行流程](#(1) 主从复制总执行流程)
- [(2) 全量复制执行流程](#(2) 全量复制执行流程)
-
- [(⭐️) 无硬盘模式](#(⭐️) 无硬盘模式)
- [(3) 部分复制流程](#(3) 部分复制流程)
- [(4) 实时复制流程](#(4) 实时复制流程)
- [三. 哨兵机制](#三. 哨兵机制)
-
- [1. 哨兵的核心性能](#1. 哨兵的核心性能)
- [2. 哨兵机制自动恢复主从复制的流程](#2. 哨兵机制自动恢复主从复制的流程)
一. 什么是主从复制?
1. 一台主机即使升级到顶级配置, 所能处理的访问量也会有极限, 再往上突破需要花费巨大的代价, 而如果我们把提升单台主机所需要的花费使用到扩充多台主机, 让多台主机同时处理高并发的请求, 那么性能的提升是十分巨大的
2. 在实际业务场景中, 用户读取数据是远大于写入数据的, 基于以上特性, 一种读写分离的数据复制技术应运而生: 主从复制
主从复制用于在多台服务器之间同步数据。其核心思想是:一个主节点(Master)负责处理数据更新,并将这些更新自动同步到一个或多个从节点(Slave)。
二. Redis的主从复制
1. 修改主节点配置文件
1. 找到/etc/redis 的redis.conf 配置文件
2. bind 修改为 0.0.0.0, 监听所有端口
3. protected-mode 修改为 no , 关闭保护模式
4. daemonize 修改为 yes 允许后台连接
2. 复制主节点配置文件并修改
1. cp 命令复制redis.conf文件, 复制两份slave1.conf, slave2.conf
2. 往新复制的配置文件中添加主从模式的配置选项
3. 修改需要监听的端口号:一个修改为6380, 一个修改为6381
4.使用redis-server 运行配置文件
3. 主从复制参数简单介绍
我们可以看到上图中redis监听了7个端口, 划红线的为一对, 划黄线的为一对, 其中主节点相当于服务器, 从节点相当于客户端
使用info replication查看主从复制的具体信息
slave no one 可以暂时关闭主从模式(修改配置文件可以实现永久关闭)
4. 特点
1. 安全性: 主节点可以通过requirepass 来设置密码, 从节点嗯对masterauth也需要和主节点保持一致, 这样客户端访问之前需要使用auth输入密码, 实现校验作用
2. 只读性: 从节点的配置 slave-read-only=yes 意味着从节点只能读取数据, 不能写入数据, 一般是默认开启的
3. 传输延迟: redis的repl-disable-tcp-nodekay 为低延迟模式, 默认为no不开启, 表示支持tcp的nagle算法, 会节省网络带宽, 如果修改为yes开启后, 会降低tcp传输延迟, 不支持nagle算法, 但会增加网络带宽
5. 拓扑结构
(1) 一主一从拓扑
1. 一主一从的拓扑结构可以解决主节点挂机时从节点来故障转移, 当读与写的请求量都处于高并发状态, 那么主节点的压力也会爆大, 因此可以关闭AOF持久化机制, 数据不再实时同步到硬盘上, 只写入内存, 减轻主节点的压力
2. 这也会导致一个问题, 当主节点崩溃时, 如果自动重启, 就会从硬盘中去恢复空数据, 从而会将从节点的数据也删除, 因此需要改变启动方式, 去从节点的AOF文件中获取数据
(2) 一主多从拓扑
一主多从拓扑结构适用于读操作占比大, 写操作占比不大的场景, 可以从主节点或者多个从节点读取数据, 只可以通过主节点写入数据, 通过网络传输来同步从节点的数据, 数据一致性较好, 该结构不适合写请求并发量较高的情况, 主节点频繁地向多个从节点发送网络数据进行同步时, 消耗的网络带宽资源较多, 会加大主节点的负载
(3) 树形拓扑
树形拓扑结构减少了主节点向从节点同步数据时的网络开销, 主节点往下一层的从节点同步数据, 从节点同步完数据后接着往更下子层的从节点来同步数据, 层层接力, 从而减轻了主节点的压力, 但该模型存在的问题主要是网络传输延迟较大, 数据同步可能较慢, 适用于对数据一致性要求不高的场景
6. psync 主从复制命令
bash
psync replicationid offset
1. psync命令为Redis主从节点同步数据的命令, 一般是Redis在主从节点建立连接后自动执行, 从节点通过主节点的 replicationid 主动拉取
2. replicationid 是主节点的复制标识id, 在主节点启动时生成, 每次重启后的replicationid 都不一样
3. offset 为偏移量, 在主节点中, 每个修改命令(类似于set/lpush/zset这样)会有相应字节数, 每执行一次修改操作, 主节点的offset会累加对应的字节数。在从节点中, offset表示当前同步进度, 当主从节点的offset值相同时, 代表同步完成
7. 复制的执行流程
(1) 主从复制总执行流程

1. 保存主节点信息: 保存的是主节点的ip与端口号, 存储在内存中
2. 主从建立连接: 通过TCP协议的三次握手建立连接, 验证通信双方能否正确读写数据
3. ping验证响应: 向主节点发送一个ping命令, 如果返回一个pong响应, 说明当前主节点可以正常工作
4. 权限验证: 如果主节点设置有密码, 需要保存主节点的密码来进行权限验证
5. 同步全量数据集: 第一次建立连接时, 或者主节点不方便进行部分复制时, 首先要将主节点当中的所有数据传输给从节点来同步
6. 持续同步增量数据集: 全量同步完成之后, 后续有数据发生改变, 通过增量同步来完成
(2) 全量复制执行流程

1) 从节点发送psync命令, 主动从主节点拉取数据, 这里假设是建立连接后的第一次复制, 从节点还不知道主节点的replid和offset, 因此psync传的参数为? 和 -1
2) 主节点接收到命令后, 知道要进行全量复制, 响应 FULLRESYNC, 并传过去自己的replid等信息
3) 从节点开始保存主节点的相关信息
4) 主节点执行bgsave, 后台生成RDB持久化文件
5) 主节点将生成的RDB文件发给从节点, 从节点保存数据, 写入到硬盘上
6) 主节点将4, 5 操作彻底完成期间所接收的修改命令, 写入到缓冲区, 等待从节点接收完成后再将这些数据同步给从节点, 保证主从节点数据的绝对一致性
7) 从节点清除原有数据
8) 从加点加载硬盘上的RDB文件
9) 从节点加载完RDB文件后, 如果本身开启了AOF功能, 就会进行bgrewrite操作, 将数据进行整合瘦身
(⭐️) 无硬盘模式
在进行全量复制的时候, 主节点也可以开启无硬盘模式, 即RDB的二进制数据直接进行网络传输到从节点, 从节点也可以直接加载数据, 不用写入到硬盘再从硬盘中读取, 这会是对全量复制性能的一个小优化
(3) 部分复制流程
部分复制发生的场景是, 主从节点因为网络抖动而导致两者的数据有一些不一致, 如果进行全量复制会较浪费时间, 因此当满足一定条件后, 会进行特殊优化, 用部分复制减少整体资源的开销

1) 超过 repl-timeout 时间后, 主节点会默认从节点已经发生故障, 这时从节点会保存主节点的replid和本身当前的offset
2) 这时主节点依旧接收请求, 进行响应, 但这些命令无法同步给从节点, 于是都保存到了挤压缓冲区
3) 主从节点之间的网络连接恢复之后, 从节点根据之前保存的replid连接主节点
4) 从节点将之前保存的 replid 和 offset 作为psync的参数传给主节点
5) 主节点验证 replid 是否与本身一致, 如果不一致, 必定进行全局复制, 如果一致, 根据传过来的 offset 去积压缓冲区去寻找, 如果积压缓冲区包含 offset , 那么说明在可恢复范围之内, 那么响应 CONTINUE , 表示可以部分复制, 反之, 当挤压缓冲区不包含 offset 时, 直接进行全局复制
6) 主节点将挤压缓冲区需要复制的数据传输给从节点, 从节点进行复制
(4) 实时复制流程
1. 实时复制指的是主从节点在当前时刻已经同步完成数据, 建立了一个TCP长连接, 之后主节点会收到新的修改命令, 从节点也要跟着同步数据。
2. 实时复制期间要保证长连接一直是可用的状态, Redis提供了心跳包机制:
即主节点每隔固定时间(默认10s)向从节点发送 ping 命令, 从节点会返回 pong 响应; 从节点每隔固定时间(默认1s)向主节点发送特定请求, 来上报当前主从复制的进度即 offset 值, 来为后续实时同步做基础
三. 哨兵机制
1. 哨兵的核心性能
1. 哨兵: 每个哨兵是一个独立的redis-sentinel进程, 负责监控主从节点之间的健康状态, 如果有特殊情况导致的宕机和超时, 会自动处理故障转移
2. 监控机制: 哨兵会与主节点和从节点的进程建立TCP长连接, 通过长连接定期发送心跳包来检查节点之间的健康状态
3. 故障转移与通知: 当主节点发生宕机之后, 哨兵接收不到主节点发送过来的心跳, 因此判定主节点挂机, 先挑选一个从节点来执行slaveof no one , 断开与主节点之间的连接, 晋升为主节点, 接着让剩余的其他从节点执行slaveof 晋升主节点的IP 端口号, 连接新的主节点, 最后通知客户端主节点已经发生改变, 后续的写请求发送到新的主节点上
2. 哨兵机制自动恢复主从复制的流程

1. 哨兵集合: 由多个哨兵组成的集合, 当有主节点宕机之后, 一个哨兵发现异常不能说明情况, 只有当多个哨兵都认定当前主节点宕机时, 才会进行判定, 主要是为了防止误判
单一哨兵来监控整个数据节点集合会有以下问题: ⬇️
① 如果单个哨兵宕机发生宕机, 当主节点发生故障挂机后, 不能及时故障转移
② 如果单个哨兵因为自身原因出现了网路波动, 没有收到来自主节点的心跳, 可能出现误判
2. 确定主节点挂机后, 会从哨兵集合中推选出领导者leader, 由leader来从现有的正常运行的从节点中, 挑选一位从节点
选取新的主节点的流程: ⬇️
1. 主观判断主节点下线: 当主节点的心跳包没有在规定时间到达哨兵时, 该哨兵就单方面主观认为主节点挂机, 这时还不能排除是不是自身的网络波动的原因
2. 客观判断主节点下线: 当多个哨兵都没有收到主节点的心跳包, 如果认为主节点挂了的哨兵数到达了法定票数(提前已经设定的个数sentinel monitor 要监控的服务器名称 要监控的服务器IP 要监控的端口号port 法定票数) 哨兵集合就认为主节点是客观下线
3. 多个哨兵节点之间选举出一个领导者 leader 节点, leader一般是网络波动最小的那个哨兵节点, 最先接收到主节点挂机的哨兵会给自己投一票, 后面收到消息的哨兵一般都会给第一个投票, 当票数大于一半时, leader就被确定下来, 所以哨兵集群节点个数一般都为奇数, 从而方便投票
4. leader 挑选新的主节点: 挑选时一般遵循以下规则 ⬇️① 优先挑优先级最高的, 配置文件中有一个 slave-priority 的选项, 优先级是第一考虑要素(默认值相同)
② 当优先级一致, 无法确定时, 就挑选从节点间的 offset 最大的那一个, 值最大说明与主节点数据最一致
③ 当优先级和offset都相同时, 就会从从节点的 run id (redis节点启动时随机生成的标识) 中随便选一个
3. 挑选出从节点后, 哨兵就会进行让其执行slaveof no one 晋升为新的主节点, 再让其他从节点连接到新主节点
4. 修改好之后, 哨兵会自动通知客户端主节点已经发生改变, 后续写操作会发送到新的主节点上










