1. 什么是主从复制
- 将master中的数据即时有效地复制到slave中。
- master负责写数据,执行写操作时,将出现变化的数据自动同步到slave中
- slave负责读数据。
2. 作用
- 读写分离,提高服务器的读写负载能力
- 负载均衡,基于主从结构,配合读写分离。有slave分担master负载。
- 故障恢复:当master出现问题时,由slave提供服务,实现快速的故障恢复
- 数据冗余:可以实现数据热备份,时持久化之外的一种数据冗余方式
- 高可用基石:基于主从复制,构建哨兵模式与集群,实现redis的高可用方案
3. 流程
3.1 补充一些概念
- Replication Id:
- 简称replid,每一个master都有唯一的replid,slave会继承master节点的replid
- 注意如果slave节点在成为slave之前也是一个master,那么它之前的replid跟成为slave之后的replid肯定不一样(即replid被替换了)
- offset:
- 偏移量,master节点和slave节点中这个offset代表了不同的含义
- 在master节点中offset会随着记录在repl_baklog(环形复制队列)中的数据增多而增大
- 在slave节点中,代表上一次同步到repl_baklog的哪个位置
- slave完成同步时会记录当前同步的offset。
- 如果slave的offset小于master的offset,说明slave数据落后于master,则需要更新
- 但这里面有一个前提,就是不能太落后了,毕竟数据存在一个环形复制队列中,有大小限制
- 即repl_baklog大小有上限,写满后会覆盖最早的数据。如果slave断开时间过久,导致尚未备份的数据被覆盖,则无法基于log做增量同步,只能再次全量同步。
- 偏移量,master节点和slave节点中这个offset代表了不同的含义
- 总结
- slave做数据同步时,会向master声明自己的replication id和offset
- master会先判断slave的replid与自己的是不是一致
- 不一致,则说明这是第一次连接,需要进行全量复制
- 一致,说明不是第一次连接,已经进行了全量复制
- master再判断slave的offset与自己的offset之间的差距是否超过repl_baklog的大小范围
- 超过了,就进行全量复制
- 没超过,就将repl_baklog中差距的部分发送过去(同时slave会保存最新的offset)
- slave节点宕机重连其实就是按照此逻辑进行数据恢复的
3.2 主从复制流程
- 建立连接阶段
- 建立slave到master的连接,是master能够识别slave,并保存slave端口号
- 步骤
- slave端设置master的地址和端口, 保存master信息(slaveof ip port)
- slave端发起socket连接
- 发送ping命令
- 身份验证
- 发送slave端信息,master端进行保存(主要作用就是当主服务器执行info replication,可以看到从服务器的端口信息)
- 主从连接建立成功
- 数据同步阶段(重点)
- slave初次连接master后(根据replid不同来判断是否初次连接),复制master中的所有数据到slave
- 将slave的数据库状态更新成master当前的数据库状态
- 步骤
- slave发送自己的replid与offset
- master判断发现与自己的replid不一致,从而确认是第一次进行连接
- master会将自己的replid与offset发送给slave,slave更新这些信息
- master还会执行bgsave,生成同步RDB数据,然后发送给slave
- slave清空本地数据,然后加载收到的同步RDB数据
- slave再请求部分同步数据(repl_baklog中的新数据,slave会发送offset)
- master会通过socket发送slave复制缓冲区信息(slave的offset与master的offset之间的数据信息)
- slave收到后会先执行bgrewtriteaof,再进行恢复部分同步数据
- 数据同步工作完成
- 命令传播阶段
- 当master数据库状态被修改后,导致主从服务器数据库状态不一致,此时需要让主从数据同步到一致状态,同步的动作成为命令传播
- master将接收到的数据变更命令发送给slave,salve接受命令后执行命令
- 本质就是主服务器作为从服务器的客户端,主服务器将自己收到到写命令不光自己执行,而且还发送给所有从服务器去执行。
4. 主从配置相关的配置
- 配置复制缓冲区大小,如果可以,这个可以设置大一点,减少全量复制次数
repl-backlog-size 10mb
- slave在进行全量、部分复制时是否对外提供服务
slave-serve-stale-data yes|no
- 给master设置密码
requirepass <password>
- 给slave设置连接master的master密码
masterauth <password>
- 给master启动无磁盘复制,避免全量同步时的磁盘IO
repl-diskless-sync yes
5. 配置主从服务器
配从不配主
5.1 方式一:从服务器客户端执行以下命令
# 在从服务器客户端上输入以下命令
# 其中127.0.0.1与6379分别时主服务器的ip地址和端口号
slaveof 127.0.0.1 6379
5.2 方式二:从服务器配置文件中配置
slaveof 172.0.0.1 3306
5.3 从服务器从主服务器中断开
# 在从服务器客户端上输入以下命令
slaveof no one
5.4 查看服务器信息
info replication
6. 主从集群优化
-
在master中配置repl-diskless-sync yes,启用无磁盘复制,避免全量同步时的磁盘IO
-
redis单节点占用内存不要太大,减少RDB导致过多磁盘IO
-
适当提高repl_baklog大小,当slave宕机时进行故障恢复时,尽可能避免全量同步
-
限制一个master上的slave数量,改成树形结构
-
master每次重启都会重新生成replid,所以应该控制这个变量不变。不然每次重启都需要大量的全量复制
7. 主从复制命令传播阶段的心跳机制
- 当进入命令传播阶段,master与slave间需要进行信息交换,使用心跳机制进行维护,实现双方连接保持在线
7.1 master会定时发送心跳
- master会定时自动发送ping命令,判断slave是否在线
- 我们可以通过info replication命令来查看slave在线信息,lag项为0或1表示正常
- 相关配置:这是定时自动发送ping命令的时间周期,默认是10秒
repl-ping-slave-period 10
7.2 slave也会周期地给master发送心跳任务(默认一秒一次)
- slave每秒会给master发送REPLCONF ACK {offset} 指令,作用:
- 汇报slave自己的复制偏移量,获取最新的数据变更指令。
- 判断master是否在线
- 辅助实现min-slaves配置选项
- 主服务器会根据收到的心跳来更新它所保留的客户端连接状态信息。
- 主服务器可以通过INFO replication来查看从服务器的状态信息