集群升级

功能目标

当需要升级server版本或者修改config配置时,都需要对集群进行升级。对于分布式集群来说,常用的升级方法就是滚动升级(Rolling-Update),即不停止服务,对一台一台server逐个进行升级。

集群升级的重要目标在于平稳,即不停服,并且对可用性的影响降至最低。为了达到这个目标,我们先看看在升级过程中哪些地方可能会影响可用性:

  • replica server进程被kill后,该进程服务的replica无法提供服务:
    • 对于primary replica:因为直接向客户端提供读写服务,所以进程kill后肯定会影响读写,需要等metaserver重新分派新的primary replica后才能恢复。meta server通过心跳感知replica server的存活状态,failure detection的时间延迟取决于配置参数fd_grace_seconds,通常配置为10秒,即最多需要经过10秒,meta server才能知道replica server挂了,然后重新分派新的primary replica。
    • 对于secondary replica:由于不服务读,所以理论上对读无影响。但是会影响写,因为一致性协议要求一主两备都写成功,写操作才能提交。进程kill后,primary replica在执行写操作过程中会发现该secondary replica已失联,然后通知meta server将其踢掉,经过reconfiguration阶段后变成一主一备,继续提供写服务。在切换过程中尚未完成的写操作,即使有reconciliation阶段重新执行,但客户端那边大概率已经超时了,对可用性有一定影响。但是这个影响相对小些,因为reconfiguration的速度是比较快的,通常在1秒以内就能完成。
  • 升级meta server:升级meta server对可用度的影响几乎可以忽略不计,因为客户端会在本地缓存各partition的服务节点信息,通常情况下并不需要向meta server查询,因此meta server重启过程中的短暂失联对客户端基本没有影响。不过考虑到meta server需要与replica server维持心跳,所以要避免连续kill meta server进程,造成replica server心跳失联的风险。
  • 升级collector:升级collector对可用度没有影响。但是可用度统计是在collector上进行的,所以可能会对统计数据有轻微影响。

因此,在集群升级过程要提高可用性,需要考虑如下几点:

  • 一次只能升级一个进程,且在该进程重启并完全恢复进入服务状态后,才能升级下一个进程。
    • 因为如果升级一个进程后,集群没有恢复到完全健康状态,有的partition还只有一主一备,这时再kill一个replica server的话,很可能进入只有一主的状态,无法提供写服务。
    • 另外,等待集群所有partition都恢复三备份后再继续升级下一个进程,也能有效降低数据丢失的风险。
  • 尽量主动迁移replica,而不是被动迁移replica,避免failure detection的时间延迟影响可用度。
    • 被动迁移需要等待failure detection来感知节点失联,而主动迁移就是在kill掉replica server之前,先将这个进程服务的primary replica都迁移到其他节点上,这个reconfiguration过程是很快的,基本1秒以内完成。
    • 更进一步,还可以在kill掉replica server之前,将这个进程服务的secondary replica手动降级,将reconfiguration过程由“写失败被动触发”变为“主动触发”,也能降低对可用度的影响。
  • 尽量减少进程重启时恢复过程的工作量,缩短进程重启时间。
    • replica server在重启时需要replay log来恢复数据。如果直接kill掉,需要replay的数据量可能很大。但是如果在kill之前,先主动触发memtable的flush操作,让内存数据先落地,在重启时需要replay的数据量就会大大减少,重启时间会缩短很多,而整个集群升级所需的时间也能大大缩短。
  • 尽量减少不必要的节点间数据拷贝,避免因为增加CPU/网络/IO负载影响可用度。
    • replica server挂掉后,部分partition进入一主一备的状态。如果meta server立即在其他replica server上补充备份,会带来大量的跨节点数据拷贝,增加CPU/网络/IO负载压力,影响集群稳定性。Pegasus解决这个问题的办法是,允许在一段时间内维持一主一备状态,给原来的replica server进行恢复的机会。如果长时间没有恢复,才会在新的replica server上补充备份。这样兼顾了数据的安全性和集群的稳定性。可以通过配置参数replica_assign_delay_ms_for_dropouts控制等待时间,默认为10分钟。

升级流程

高可用升级

根据以上对高可用度的考虑,我们建议完善的升级流程如下:

  • 准备好新的Server程序包和配置文件
  • 使用shell工具将集群的meta level设置为steady,关闭负载均衡功能,避免不必要的replica迁移
    >>> set_meta_level steady
    
  • 升级replica server进程,采用逐个升级的策略。升级单个replica server:
    • 通过shell向meta server发送远程命令,禁掉add_secondary操作:
      >>> remote_command -t meta-server meta.lb.add_secondary_max_count_for_one_node 0
      
    • 通过migrate_node命令,将replica server上的primary replica都迁走:
      $ ./run.sh migrate_node -c $meta_list -n $node -t run
      

      通过shell的nodes -d命令查看该节点的服务replica情况,等待primary replica的个数变为0;如果长时间不变为0,重新执行上面命令。

    • 通过downgrade_node命令,将replica server上的secondary replica都降级为INACTIVE:
      $ ./run.sh downgrade_node -c $meta_list -n $node -t run
      

      通过shell的nodes -d命令查看该节点的服务replica情况,等待secondary replica的个数变为0;如果长时间不变为0,重新执行上面命令。

    • 通过shell向replica server发送远程命令,将所有replica都关闭,以触发flush操作,将数据都落地:
      >>> remote_command -l $node replica.kill_partition
      

      等待大约1分钟,让数据完成落地。

    • 通过shell向meta server发送远程命令,开启add_secondary操作:
      >>> remote_command -t meta-server meta.lb.add_secondary_max_count_for_one_node 100
      
    • 替换程序包和配置文件
    • 重启meta server进程
    • 使用shell的ls -d命令查看集群状态,等待所有partition都完全恢复健康
    • 继续升级下一个replica server
  • 升级meta server进程,采用逐个升级的策略。升级单个meta server:
    • kill掉meta server进程
    • 替换程序包和配置文件
    • 重启meta server进程
    • 等待30秒以上,保证meta server与replica server心跳的连续性
    • 继续升级下一个meta server
  • 升级collector进程:
    • kill掉collector进程
    • 替换程序包和配置文件
    • 重启collector进程

简化版升级

如果对可用性要求没那么高,升级流程可简化如下:

  • 准备好新的Server程序包和配置文件
  • 使用shell工具将集群的meta level设置为steady,关闭负载均衡功能,避免不必要的replica迁移
    >>> set_meta_level steady
    
  • 升级replica server进程,采用逐个升级的策略。升级单个replica server:
    • kill掉replica server进程
    • 替换程序包和配置文件
    • 重启replica server进程
    • 使用shell的ls -d命令查看集群状态,等待所有partition都完全恢复健康
    • 继续升级下一个replica server
  • 升级meta server进程,采用逐个升级的策略。升级单个meta server:
    • kill掉meta server进程
    • 替换程序包和配置文件
    • 重启meta server进程
    • 等待30秒以上,保证meta server与replica server心跳的连续性
    • 继续升级下一个meta server
  • 升级collector进程:
    • kill掉collector进程
    • 替换程序包和配置文件
    • 重启collector进程

升级脚本

我们提供了集群升级脚本scripts/pegasus_rolling_update.sh。该脚本采用高可用升级流程,用于小米内部的集群升级。

不过这个脚本并不能直接使用,因为其依赖minos部署工具来完成以下事情:

  • 获取集群的进程列表
  • 自动部署更新程序包和配置文件,并重启进程

你可以修改该脚本,针对你们自己的部署系统,修改以上通过minos完成的部分,使其可以正常工作。如需帮助,请联系我们。

Apache Incubator
Copyright © 2020 The Apache Software Foundation. Licensed under the Apache License, Version 2.0.

Apache Pegasus is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, it does indicate that the project has yet to be fully endorsed by the ASF.