主从服务器的心跳检测机制
    Redis的复制功能分为同步(sync)和命令传播(command propagate)两个操作:
    * 同步操作用于将从服务器的数据库状态更新至主服务器当前所处的数据库状态、
    * 命令传播操作则用于在主服务器的数据库状态被修改,导致主从服务器的数据库状态出现不一致时, 让主从服务器的数据库重新回到一致状态。

    同步:
        当客户端向从服务器发送SLAVEOF命令,要求从服务器复制主服务器时,从服务器首先需要执行 同步操作,也即是,将从服务器的数据库状态更新至主服务器当前所处的服务器状态。
    
     SYNC命令时一个非常耗费资源的操作
    每次执行SYNC命令,主从服务器需要执行以下动作:
     1. 主服务器需要执行BGSAVE命令来生成RDB文件,这个生成操作会耗费主服务器大量的CPU,内存和磁盘 I/O 资源。
     2. 主服务器需要将自己生成的RDB文件发送给从服务器,这个发送操作会耗费主从服务器大量的网络资源(带宽和流量),并对主服务器响应命令请求的时间产生影响。
     3. 接收RDB文件的从服务器需要载入主服务器发来的RDB文件,并且在载入期间,从服务器会因为阻塞而  没办法处理命令请求。


新版本: 使用PSYNC命令代替SYNC命令来执行复制时的同步操作。

PSYNC命令具有完整重同步(full resynchoronization)和部分重同步(partial resynchoronization)两种模式:
        * 其中完整重同步用于处理初次复制情况:完整重同步的执行步骤和SYNC命令的执行步骤基本一样它们都是通过让主服务器创建并发送RDB文件,以及向从服务器发送保存在缓冲区里面的写命令来 进行同步。
        * 而部分重同步则用于处理断链后重复制情况:当从服务器在断链后重新连接主服务器时,如果条件允许,主服务器可以将主从服务器连接断开期间执行的写命令发送给从服务器,从服务器只要接收并执行这些写命令,就可以将数据库更新至主服务器当前所处的状态。
    
    部分重同步功能由一下三个部分组成:
        * 主服务器的复制偏移量(replication offset)和从服务器的复制偏移量。
        * 主服务器的复制积压缓冲区(replication backlog)
        * 服务器的运行ID(run ID)
    复制积压缓冲区
        复制积压缓冲区是由主服务器维护的一个固定长度(fixed-size)先进先出(FIFO)队列,默认大小为1MB。
    当从服务器重新连接上主服务器时,从服务器会通过PSYNC命令将自己的复制偏移量offset发送给主服务器,主服务器会根据这个复制偏移量来决定对从服务器执行何种同步操作:
        * 如果offset偏移量之后的数据(也即是偏移量offset+1 开始的数据)仍然存在复制积压缓冲区 里面,那么主服务器将对从服务器执行部分重同步操作。
        * 相反,如果offset偏移量之后的数据已经不存在复制积压缓冲区,那么主服务器将对从服务器执行完整重同步操作。

      根据需要调整复制积压缓冲区的大小
    Redis为复制积压缓冲区设置的默认大小为1MB,如果主服务器需要执行大量写命令,又或者主从服务器 断链后重连所需要的时间比较长,那么这个大小也许并不合适。
    如果复制积压缓冲区的大小设置得不恰当,那么PSYNC命令的复制重同步模式就不能正常发挥作用,因此,正确估算和设置积压缓冲区的大小非常重要。
        复制积压缓冲区的最小大小可以根据公式second* write_size_per_second来估算:
        * 其中second为从服务器断链后重新连接上主服务器所需的平均时间(以秒计算)。
        * 而write_size_per_second则是主服务器平均每秒产生的写命令数据量(协议格式的写命令的 长度总和)。 至于复制积压缓冲区大小的修改方法,可以参考复制文件中关于repl-backlog-size选项的说明。 

       积压队列在本质上是一个固定长度的循环队列,默认情况下积压队列的大小为1MB,可以通过配置文件的repl-backlog-size选项来调整。很容易理解的是,积压队列越大,其允许的主从数据库断链的时间越长。根据主从数据库之间的网络状态,设置一个合理的积压队列很重要。因为积压队列存储的内容是命令本身,如 set foo bar,所以估算积压队列的大小只需要估计主从数据库断链的时间中主数据库可能执行的命令的大小即可。

    也积压队列相关的另一个配置选项是repl-backlog-ttl,即当所有从数据库与主数据库断开连接后,经过多久时间可以释放积压队列的内存空间。默认时间是1小时。


心跳检测
    在命令传播阶段,从服务器默认会以每秒一次的频率,向主服务器发送命令:
    REPLCONF ACK <replication_offset>
    其中 replication_offset 是从服务器当前的复制偏移量。
    发送REPLCONF ACK 命令用于主从服务器有三个作用:
     * 检测主从服务器的网络连接状态
     * 辅助实现min-slaves选项。
     * 检测命令丢失


总结
    * Redis 2.8 以前的复制功能不能高效地处理断线后重复制情况,但Redis2.8新添加的部分重同步功能可以解决这个问题
    * 部分重同步通过复制偏移量、复制积压缓冲区、服务器运行ID三个部分来实现。
    * 在复制操作刚开始的时候,从服务器会成为主服务器的客户端,并通过向主服务器发送命令请求来 执行复制步骤,而在复制操作的后期,主从服务器会相互成为对方的客户端。
    * 主服务器通过向从服务器传播命令来更新从服务器的状态,保持主从服务器一致,而从服务器则通过向主服务器发送命令来进行心跳检测,以及命令丢失检测。