#kvrocks
```mermaid
sequenceDiagram
actor User
participant Slave
participant Master
User -) Slave: SLAVEOF
opt AUTH
Slave ->> Master: AUTH xxx
Master -->> Slave: OK
end
Slave ->> Master: _db_name
Master -->> Slave: master's dbname
Slave ->> Slave: 检验 dbname 相同
Slave ->> Master: replconf listening-port {slave-port}
Master -->> Slave: OK
Note over Slave,Master: 尝试进行 PSYNC
Slave ->> Master: PSYNC {next_seq}
Master ->> Master: WAL 中是否有<br/> next_seq
alt 有,psync
rect rgb(191, 230, 158)
Master ->> Master: 开启<br/> FeedSlaveThread
rect rgb(193, 245, 204)
loop batch loop
Master ->> Master: 迭代 WAL
Master -) Slave: write batches
Slave ->> Slave: ApplyWriteBatch
Note right of Slave: 定时或 master 要求时发送 ack
Master -) Slave: _getack
Slave -) Master: replconf ack {cur_seq}
end
end
end
else 没有,full sync
rect rgb(191, 223, 255)
Slave ->> Master: _fetch_meta
Master ->> Master: 检查或创建<br/> checkpoint
Master -->> Slave: checkpoint file list
Slave ->> Master: _fetch_file file1,file2,...
Master -->> Slave: <file_size, file_data>, ...
Slave ->> Slave: restoreFromCheckpoint
Slave ->> Slave: 重试 PSYNC
end
end
```
- dbname 校验:
- slave 和 master 配置文件里的 db-name 必须相同才能复制,避免集群 mismatch
- replconf listening-port
- 向 master 通告 slave 的监听端口,用于 info 等命令展示
- 当 slave 配置了 replica-announce-ip 选项后,还会发送 ip 地址,格式:
- `replconf listening-port {port} ip-address {ip}`
- 用于应对 NAT 等场景。默认不启用,master 从 slave 链接上获取 ip
- [Support for replica-announce-ip and replica-announce-port #481](https://github.com/apache/kvrocks/discussions/481)
- psync 命令
- 可以携带 **`replication_id`**: `psync replication_id next_seq`
- [PSYNC based on Unique Replication Sequence ID #538](https://github.com/apache/kvrocks/pull/538)
- master 换了,同一个seq 前后两个master上的内容可能不同,因此每个变更添加此ID(PutLogData),同步时同时校验 id + seq,不同 master 的 replication_id 不同
- replica_id + seq 都相同表示数据一样
- 重启或提升为 master 后重置
- **`next_seq`**: `db_->GetLatestSequenceNumber() + 1`
- full sync
- master 生成 checkpoint 再传输目录下的文件
- 相对 backup,checkpoint 使用硬链接,磁盘占用很小
- fetch files
- 多线程并行执行
- 保存目录:sync_checkpoint
- 如果目录中有同名文件且 *crc 相同* 则表示已经 fetch 过,无需再次 fetch
- 附加条件:ReplicationThread::Start 时需要清理 sync 目录,删除旧 master 同步过来的数据。(不同 master 的文件名相同,但内容可能不同)。
- restoreFromCheckpoint
- 先重命令老DB,如果 restore 失败则回滚(恢复老DB)
- restore 成功则删除老DB