Pika ReplicationID 方案

背景

Pika 目前处于切主操作时,其他从节点会和新主节点进行全量同步,但是在执行切主操作发生之前,原本的从节点和新主节点的数据是基本一致的 (因为在旧主正常运行时,各个从节点的数据基本一致),所以我们认为在做切主操作时我们应该进行的是从节点与新主节点之间执行增量同步

改进方案

当第一个从实例对主进行 slaveof ip port 的时候,主节点生成 ReplicationID,将生成的 ReplicationID 持久化到从节点。Pika 实例启动时候的 ReplicationID:Offset 默认为 0:-1;同时我们提供一个接口给运维的同学 ClearReplicateID,这个命令是运维的同学对离开集群的节点进行操作的,功能是将离开集群节点的 ReplicationID 置为默认的 0

全量复制和增量复制判断

当一个从实例连接主实例时,发送 slaveof 命令去进行主从同步,slave 会把它持有的 ReplicationID 发送给 master,与 master 的 ReplicationID 和 Offset 做比较,这样就能获取缺失的增量数据。但是如果 master 的 buffer 中 Offset 偏移量过大或者从实例所持有的 ReplicationID 在当前的 master 中匹配不到,那么从实例就会进行一次全量同步。

当一个从实例需要重启时,重启后如果想要只进行增量同步,只需要同步 ReplicationID 及 Offset 给主实例即可。
增量复制及全量复制的几种情况:

  1. 从实例的 ReplicationID 在主实例中匹配不到,Offset = -1,全量复制

  2. 从实例的 ReplicationID 在主实例中能匹配到,Offset 偏移量过大,全量复制

  3. 从实例的 ReplicationID 在主实例的 ReplicationID 能够匹配到,Offset 偏移量在范围内,增量复制

问题

  • ClearReplicateID 底层调用的是 configset 去更改 ReplicationID 的值,这个值是在内存中,如果此时实例宕机重启了那么 ReplicationID 将查询不到?

    我们的想法是执行 ClearReplicateID 的时候调用 configset 修改 ReplicationID 值再重载一下 rewrite 方法并调用使其将 ReplicationID 的值持久化到硬盘上

  • 一个集群内的 ReplicationID 一定是唯一的吗?

    是的,一个集群只维护一个 ReplicationID,ReplicationID 生成与第一个从 slaveof 主节点的时候,由主节点生成持久化到 config 文件中,并且将 Replication ID 持久化到从节点的 config 文件中

  • 从节点掉线重连之后,ReplicationID 还能获取到吗?

    可以的,因为 ReplicationID 是持久化到每个实例的配置文件中,所以每次上线时候可以获取到 ReplicationID

  • 怎么去判断 ReplicartionID 的生成条件?

    由于每个实例启动的时候 ReplicationID 默认为空字符串,只有当主从第一次数据同步时,系统判断主节点自身的 ReplicationID 是否为空,如果是空,则生成 ReplicationID 否则将不生成。所以当有切主操作时,不会生成新的 ReplicationID,我们可以认为当一个集群第一次建立时,这个 ReplicationID 的值就确立了并且不会更改,除非这个集群完全消失

  • ReplicationID 什么时候清空?

    有两种情况:

    1. 当实例调用 shutdown 进程退出的时候,调用 ClearReplicateID 清空 ReplicationID
    2. 当实例离开当前集群的时候,调用 ClearReplicateID 清空 ReplicationID

    注意线上环境的时候这个操作一般是运维的同学执行

异常情况

  • 实例起来时用 info replication 查看 replicationID 是否是空
  • 主从复制时查看 conf 文件中是否 replicationID 已经持久化
  • 一主两从情况下,主节点下线,2 号从节点马上 slaveof 1 号从节点
  • 一主两从情况下,主节点下线,2 号从节点马上 slaveof 1 号从节点,此时主节点写两分钟数据,然后 2 号从节点再 slaveof 主节点
  • 一主两从情况下,主节点下线, 1 号从节点继续写 2 分钟的数据,然后 2 号从节点 slaveof 1 号从节点
  • 一主两从情况下,主节点执行 ClearReplicateID 下线再上线, 1 号从节点和 2 号从节点 slaveof 主节点
  • 一主两从情况下,1 号从节点和 2 号从节点 slaveof 主节点的中途对主节点执行 ClearReplicateID
  • 一主两从情况下,1 号从节点和 2 号从节点 slaveof 主节点执行完毕后对主节点执行 ClearReplicateID,再次 slaveof 主节点
  • 一主两从情况下,1 号从节点和 2 号从节点 slaveof 主节点执行完毕后对一个从节点执行 ClearReplicateID,再次 slaveof 主节点
  • 一主两从情况下,1 号从节点和 2 号从节点 slaveof 主节点执行完毕后对一个从节点执行 ClearReplicateID,再次 slaveof 主节点