Redis(六)高可用Redis

上篇博客详细介绍了主从复制流程及原理,这里对主从复制的其它细节、问题及优化进行一个整理。

  • 心跳检测
  • 复制超时与中断
  • 哨兵模式
  • 集群

心跳检测 
  在命令传播阶段,除了发送写命令外,主从节点还通过心跳检测机制(通过发送PING、REPLCONF ACK命令)来检测彼此状态,心跳检测通过周期性调用replicationCrom()函数来实现。

/* Replication cron function, called 1 time per second. 每秒执行一次*/
void replicationCron(void) {
    ......

    /* Send ACK to master from time to time.
     * Note that we do not send periodic acks to masters that don't
     * support PSYNC and replication offsets. */
    /* 发送REPLCONF ACK <offset>命令 */
    if (server.masterhost && server.master &&
        !(server.master->flags & CLIENT_PRE_PSYNC))
        replicationSendAck();

    ......
    /* 每10秒发送一次PING命令,repl_ping_slave_period配置默认为10 */
    /* First, send PING according to ping_slave_period. */
    if ((replication_cron_loops % server.repl_ping_slave_period) == 0) {
        ping_argv[0] = createStringObject("PING",4);
        replicationFeedSlaves(server.slaves, server.slaveseldb,
            ping_argv, 1);
        decrRefCount(ping_argv[0]);
    }   
    ......
}

1)主节点默认每10秒向从节点发送一次PING命令,从节点每次收到PING指令后,更新最后检测的时间,之后从节点在每次执行replicationCron()时都会检测距离上次主从交互的时间是否超过了repl-timeout,如果超时则终止连接。


# 主节点向从节点发送ping的周期<官方文档有误,通过分析源码来看,这里是主节点向从节点发送PING
# repl-ping-slave-period 10

# 复制超时时间 
# repl-timeout 60

2)从节点每秒向主节点发送一次REPLCONF ACK <offset>,向主节点提供自己的复制偏移量。这个命令可以检测主从网络连接状态、命令是否丢失并且保证数据的最终一致性、以及辅助保证主节点在不安全的情况下不执行写命令
  如果主节点超过一秒没有收到该命令则说明网络连接可能出现了故障,通过info replication可以查看j最后一次发送的时间,lag=1表示最后一次接收到该命令是在1秒前。正常情况下这个值应该在0-1,如果大于1则说明存在延迟或故障。

  此外由于命令传播以异步的方式运行,主节点只进行命令的传输,并不等待从节点的响应,所以主从数据的一致性存在一定的延迟,甚至可能数据不同步,比如命令丢失。但由于复制积压缓冲区的存在,所以在后续的repconfi ack <repl_offset>到来时,主从节点数据将最终一致。
  此外Redis主节点中使用min-slaves-to-write和min-slaves-max-lag参数,来保证主节点在不安全的情况下不执行写命令。在从节点数量太少,或延迟过高,比如有从节点个数小于5个,或者所有从节点的延迟大于M秒,则拒绝执行写命令。而这里的延迟值对应的就是info replication中的lag。

# 当从节点个数<N,或N个从节点延迟>M时,主节点将拒绝执行写操作。
# 延迟时间的计算为:当前时间 - 从节点最后一次向主节点发送REPLCONF ACK <offset>命令的时间
# min-slaves-to-write 3
# min-slaves-max-lag 10

复制超时与中断
  redis复制超时默认为60秒,由repl-timeout配置指定,对于主从节点都有效,同样redis通过每秒执行一次replicationCron()来判断是否步超时。
  对于主节点而言,如果当前时间距离上次收到各个从节点REPLCONF ACK的时间,超过了repl-timeout值,则认为超时,主节点将释放相应从节点的连接。
  从节点的判断相对较为复杂,在连接建立阶段,如果距离上次收到主节点的信息的时间已超过repl-timeout,则释放与主节点的连接;在数据同步阶段,如果接收主节点RDB文件超时,则停止数据同步释放连接;在命令传播阶段,且距离上次收到主节点的PING或数据的时间已超过repl-timeout值,则释放与主节点的连接。

注意点:
       在数据同步阶段,可能由于数据量过大导致复制超时,这种情况下除了注意Redis单机数据量不要过大外,可以适当的调整repl_timeout值,一般可以设置成1.5*bgsave的时间。而且repl-timeout的值必须大于repl-ping-slave-period,否则很可能在复制期间从节点就把连接给断开了,一是因为复制时间一般会比较长,二是因为如果丢失了某次PING的情况下有可能导致从节点断开连接。比如主节点10秒发送一次PING,本来丢失一次的情况下影响并不大,主节点在10秒之后会再次发送PING,但如果此时repl_timeount设置为<10,且恰巧在这10秒内主节点也没有发送数据至从节点,就会因为超时导致从节点释放连接。除此之外,keys*、hgetall等操作在数据量很大的情况下也可能导致服务器阻塞,阻塞期间无法响应复制连接中对方节点的请求,引起超时。
  除了复制超时导致的中断外,网络故障、执行slaveof no one等等,都会导致复制中断。对于由于网络导致的连接中断,从节点将不停的尝试重连。

  
哨兵模式(Sentinel)
  Sentinel是Redis高可用性的一种方案,通过一个或多个Sentinel实例组成的哨兵系统,可以监控任意多个主节点,及其下的从节点。当主节点下线时,Sentinel通过选举的方式自动将其下的某个从节点升级为主节点,其它从节点成为新主节点的从节点,当原主节点上线时,将成为新主节点的从节点。Sentinel默认每10秒向主节点发送一次INFO命令,通过回复内容,可以获取主节点及其从节点信息。当发现主节点有新节点加入时,Sentinel将建立与新节点的命令连接和订阅连接。
Sentinel默认每2秒向从节点发送一次INFO命令,获取从节点状态。

图例如下


主从复制作用基本可以概括如下

  1. 主从DB存储冗余数据,实现数据备份
  2. 通过读写分离达到负载均衡
  3. 通过哨兵模式实现转移故障
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值