08.主从同步-Slave
约 1063 字大约 4 分钟...
为什么使用主、从架构:
- 单机下如果宕机,通过AOF、RDB恢复需要时间。服务会出现中断,为了
高可用性
- 单机性能存在瓶颈上限,主、从可以提升读操作的瓶颈上限,为了
高性能
主、从模式特点:
- 主、从之间的数据同步操作是异步进行的,属于弱一致性(最终一致)
- 通过冗余解决可用性问题:
- 数据冗余(每个节点都存数据)
- 服务冗余(每个节点都可以提供读服务,不支持写)
- 冗余带来的新问题:
- 主、从数据的一致性问题:
- Redis提供了主从复制模式,避免数据不一致
- 多服务的通信问题:
- 主、从心跳监测
- 哨兵机制
- 主、从数据的一致性问题:
- 读、写分离:
- 读操作:主、从都可以接收命令
- 写操作:仅主库接收命令,执行后同步给从库
主、从首次同步
流程:
- 命令:
replicaof/slaveof 主库IP PORT
- 流程:
- runID: 每个实例唯一id;
- offset:表示首次复制;
- FULLRESYNC:全量复制
- replication buffer: 主库RDB文件生成后,收到的所有写操作存储在该buffer
- 过程说明:
- 第一阶段:
协商
- 从库给主库发送:
psync ? -1
- 表示要进行数据同步,因为不知道主库的runID所以设置
?
,且首次offset=-1
- 表示要进行数据同步,因为不知道主库的runID所以设置
- 主库收到
psync
命令,发送:FULLRESYNC runID offset
- 告诉从库主库的ID、以及主库目前的复制进度offset
- 从库给主库发送:
- 第二阶段:
RDB数据同步
- 主库执行
bgsave
生成RDB文件,将RDB文件
同步给从库 - 从库收到RDB数据后,清空先前数据并加载收到的RDB数据
- 从库完成加载,回复
ACK
给主库
- 主库执行
- 第三阶段:
增量数据同步
- 主库把第二阶段执行过程中,新收到的存放在
replication buffer
中的写命令
发送给从库 - 从库有序执行这些
写命令
,首次同步即完成
- 主库把第二阶段执行过程中,新收到的存放在
- 后续:
- 第一次主、从同步后,主、从TCP连接会一直维持着
- 主库后续的增量数据都会通过
replication buffer
缓冲区,传给从库。
- 第一阶段:
- 主节点复制缓冲区
replication buffer
:- 主库会为
每个从库
创建一个单独的缓冲区 - 该缓冲区的默认大小是
32M
- 设计的目的:
确保命令的实时性、有序性、完整性和传输的可靠性
(与AOF缓冲区作用相似,一个是磁盘IO、一个是网络IO) - 当
replication buffer
满了,会导致连接断开,主库删除缓存,从节点重新连接并重新开始全量复制
- 主库会为
主、从断联后的增量同步
流程:
发生时机:
- 当第一次主、从同步的TCP长连接因为网络原因中断,又重新连接时
流程:
- 过程说明:
- 主、从库的连接恢复
- 从库给主库发送
psync 自己runID offset
命令,并把自己当前的 slave_repl_offset作为offset
发给主库 - 主库会判断自己的
master_repl_offset
和slave_repl_offset
之间的差距,如果有差距发送CONTINUE
命令 - 主库把 master_repl_offset 和 slave_repl_offset 之间的
写命令操作
,同步给从库
- 过程说明:
repl_backlog_buffer
:
- 主库
只有一个
repl backlog buffer - 该缓冲区的默认大小是
1M
- 写时机:主、从首次同步完成后,主服务器进行
命令传播
时,开始将增量写操作写入repl_backlog_buffer
,然后通过replication buffer
发送 - repl_backlog_buffer 是一个
环形缓冲区
,写满后会覆盖写 - 覆盖写的问题:
- 如果从库的读取速度比较慢,主库写入速度快,会导致从库还未读取的命令被主库写覆盖,这样会导致主、从库间的数据不一致,会再次触发低效的
全量同步
- 如果从库的读取速度比较慢,主库写入速度快,会导致从库还未读取的命令被主库写覆盖,这样会导致主、从库间的数据不一致,会再次触发低效的
- 覆盖写问题的优化:
- 设置合适的repl_backlog_size
所需缓冲空间大小
=主库写入命令速度 * 操作大小 - 主从库间网络传输命令速度 * 操作大小
(生产速度-消费速度)repl_backlog_size
=所需缓冲空间大小
* 2(做冗余)