《Redis开发与运维》第六章笔记

248 阅读6分钟
原文链接: idealv.github.io

第六章 复制

为了满足故障恢复和负载均衡,只靠单个Redis节点是不够的。其中最基础的方式就是用复制来实现的,
后续的哨兵和集群都依赖于复制

6.1.复制的建立断开与切换

复制中的数据流向的两头分别为主节点和从节点(且复制反向只能从从节点到主节点,同时从节点默认只读),默认每个Redis节点都是主节点,当建立复制的时候,一个节点会成一个主节点的从节点,
这个操作通过slaveof命令实现

127.0.0.1.6380>slaveof 127.0.0.1.6379 //6380的Redis节点成为6379主节点的从节点

执行完操作后主/从节点的复制状态信息中就能查看到对于从/主的信息了

127.0.0.1.6379>info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,status=online,offset=42

127.0.0.1.6380>info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379

断开连接:通过slaveof no one来断开主从节点间的连接,同时从节点恢复主节点的身份,且从节点保留之前的主节点上的数据

切换主节点:通过slaveof {newHost}:{newPort}来与另一个主节点来建立复制关系
1) 断开与原主节点复制关系
2) 与新主节点建立复制关系
3) 删除从节点现有数据
4) 复制新主节点数据

6.2.复制原理

1) 保存主节点信息(master_host,master_port …)
2) 主从建立socket连接(如果无法建立连接则通过slaveof no one来断开连接,并打印错误日志)
3) 发送ping命令(确认socket是否可用,主节点是否能够响应。如果主节点没有发送pong响应,则断开连接,在下次定时任务发起重连)
4) 权限验证(主节点设置requirepass的情况下,从节点需要携带masterauth参数并确保和主节点的requirepass参数相同从而通过验证)
5) 同步数据集(具体复制操作参见6.2.1)
6) 命令持续复制(后续主节点写入的数据同步到从节点中去)

6.2.1.数据同步

  • 全量复制(适用于初次复制)
  • 部分复制(在主从节点意外断开连接后通过部分复制将丢失的数据复制给从节点)

新版Redis主要使用psync来进行复制,执行psync要确保以下内容

  • 主从节点复制offset
  • 复制积压缓冲区
  • 主节点运行Id

1.主从节点复制offset

  • 主节点在执行写入操作后会将命令的字节长度累加记录到offset中去,这个值可以通过info replication中的master_repl_offset查看
  • 从节点收到主节点发送的数据后,也会累加自己的offset,可以通过info replication中的slave_repl_offset获取
  • 从节点每秒上报自己的offset到从节点中去,主节点可以通过info replication中的slave{slaveNo}: offset获取

通过计算master_repl_offset - slave_offset可以得出主从节点相差的数据量

2.复制积压缓冲区

复制积压缓冲区是主节点上的一个固定长度的队列,当主节点有连接的从节点时,主节点执行写命令的时候不仅会把命令同步到从节点中去,
也会写入复制积压缓冲区中去,因为复制积压缓冲区定长的先入先出的性质可以用来部分复制和恢复最近丢失的数据

3.主节点运行Id

每个Redis启动后都会被分配一个40位的十六进制字符串作为唯一标识的Id。之所以不使用Host:Port的方式来唯一标识主节点是因为,
当主节点重启且数据变更后(RDB和AOF改变),从节点再再基于偏移量来复制数据(此时因为数据变更了,所以主节点的偏移值无法保证正确)将会不安全了。所以为了确保不会发生这种问题,当运行Id变化后(重启后运行Id会变化)从节点将会执行全量复制。

不改变运行Id的情况下重启:redis cli debug reload

4.psync

从节点通过psync来进行全量和部分复制

psync {runId} {offset} //runId:从节点运行Id offset:从节点已经复制的偏移量,意思就是在主节点上复制这个偏移量之后的数据

psync执行过程
1) 从节点发送psync {runId} {offset}给主节点
2) 主节点判断psync参数

- 如果回复+FULLRESYNC {runId} {offset},那么从节点进行全量复制
- 如果回复+CONTINUE,从节点进行部分复制
- 回复+ERR,说明当前版本不支持psync,从节点发送sync进行全量复制

6.2.2.全量复制

1) 发送psync,由于是第一次建立连接没有从节点没有主节点的runId和偏移量,所以发送psync -1
2) 主节点根据psync -1判断当前是全量复制,返回+FULLRESYNC
3) 从节点收到主节点响应,保存主节点运行Id和偏移量
4) 主节点执行bgsave生成RDB文件
5) 主节点发送RDB文件给从节点,从节点将RDB保存在本地
6) 在主节点发送RDB到从节点接收完毕的过程中,主节点任响应外部操作,这是主节点会将这些新数据缓存在复制缓冲区中,当从节点加载
完RDB文件后,再将缓冲区内的数据发送给从节点,防止数据丢失和主从一致性
7) 从节点接受完主节点的数据后清空本地的就数据
8) 从节点加载RDB文件
9) 如果当前从节点开启了AOF,会立刻执行bgrewriteaof操作,保证全量复制后AOF机制仍然能正常工作(因为清空了旧数据又导入主节点数据)

6.2.3.部分复制

因为全量复制开销过大,所以Redis引入了部分复制的机制。当从节点复制主节点时发生了异常导致数据丢失的情况下,
发送psync {runId} {offset}重新获取丢失的数据,如果复制积压缓冲区中有这部分数据则发送给从节点,这样传输的数据量
远远小于全量复制
1) 主从节点网络中断,当超过repl-tiemout时,主节点任务从节点故障并断开连接
2) 断开连接期间主节点仍然响应操作,将写命令缓存到复制积压缓冲区中
3) 从节点网络恢复后,重新连接上主节点
4) psync {runId} {offset}要求补发数据
5) 主节点校验参数,如果runId等于自己的runId且offset之后的数据在复制积压缓冲区中则返回+CONTINUE
6) 主节点从缓冲区中将数据发送给从节点