第15章 复制
redis服务器B执行slave of命令后可变成另一台服务器的从库:
1 | 127.0.0.1:12345> SLAVEOF 127.0.0.1 6379 |
旧版复制功能的实现
- 同步(
sync
): 更新从库状态; - 传播(
propagate
): 持续维持一致性。
同步
主库发RDB文件给从库,从库载入一下。
旧版缺点:
每次断线后,重新同步,也就是重新生成RDB文件,重新全量载入。
新版复制功能的实现(2.8+版本)
引入PSYNC
命令,它有两种模式:
- 完整重同步: 初次复制;
- 部分重同步:断线重连。
部分重同步:
- 主从库的复制偏移量;(replication offset)
- 主库的复制积压缓冲区;(replication backlog):默认1MB,FIFO队列。
- 服务器的运行id(run ID)。
如果重连时,需要的数据还在缓冲区,就部分同步;
如果重连时,需要的数据已经被删除,就完全同步。
所以缓冲区设置稍微大一些最好。
复制流程
- 从库:记录主库地址端口等信息到内存;
- 建立套接字连接;
- 从库: PING 主库: PONG,确认连接健康;
- 身份验证:(是否需要认证,密码),两个维度都需要相同才能继续;
- 从库=>主库: 请用xxx端口联系从库;
- 同步: 主库从库互为客户端:
完全同步: 主库=>从库: 保存在缓冲区的写命令;
部分同步: 主库=>从库: 保存在复制积压缓冲区的写命令。 - 命令传播: 主库=>从库: 新的写命令。
心跳检测
从库=>主库:
1 | REPLCONF ACK <replication_offset> # 从库当前复制偏移量 |
三个作用:
- 主库确定各个从库的健康状态;
- 检测命令丢失:主库检测从库有没有漏的复制,漏则重发;
min_slave_to_write
参数:如果配置了这个,主库可以在从库太少的时候拒绝写命令。
slaveof命令源码细节
从库确认收到主库的完整rdb文件后,才清空旧数据库。
(而不是说不分青红皂白上来就把自己清空了,那就太傻了。)
相关代码(https://github.com/huangz1990/redis-3.0-annotated/blob/unstable/src/replication.c):
1 | /* Check if the transfer is now complete */ |