关于高可用的系统一点思考

2016-11-11 17:42:34

写在前面,此文章为转载,略微整理

理解高可用系统

高可用,顾名思义就是要我们的计算环境(包括软硬件)做到full-time的可用性。通常在需要做好如下设计:

  • 对软硬件的冗余,以消除单点故障。任何系统都会有一个或多个冗余系统做standby
  • 对故障的检测和恢复。检测故障以及用备份的节点接管故障点。就是我们常说的failover
  • 需要很可靠的交汇点(CrossOver)。eg. 域名解析、负载均衡等

说起来很简单,然而,细节决定成败,冗余节点最大的难题就是有状态的节点数据复制和数据一致性的保证(无状态节点冗余相对简单):

  • 如果系统的数据镜像到冗余节点是异步的,那么failover的时候就会出现数据差异
  • 如果系统在数据镜像到冗余节点是同步的,那么会导致冗余节点越多性能越慢。

所以,很多高可用系统都是在做各种取舍,这需要比对着业务的特点来的,比如银行账号的余额是一个状态型的数据,那么,冗余时就必需做到强一致性,再比如说,订单记录属于追加性的数据,那么在failover的时候,就可以到备机上进行追加,这样就比较简单了。

下面,总结一下高可用的设计原理:

  • 要做到数据不丢,就必须持久化
  • 要做到服务高可用,必须有备用,无论是应用结点还是数据结点
  • 要做到复制,就会有数据一致性的问题
  • 我们不可能做到100%的高可用,即我们能做到几个9的SLA

高可用技术方案的示例

简单解释一下MySQL的这几个方案(主要是想表达一个越多的9就越复杂)

  • Mysql Repleaction(一般配合keepalived 实现failover) 是传统的异步数据同步或是半同步Semi-Sync(只要有一个slave收到更新就返回成功)这个方式本质上不到2个9)
  • MMM/MHA通过MySQL replication技术可以实现两个服务器互为主从,且在任何时候只有一个节点可以被写入,避免了多点写入的数据冲突。同时,当可写的主节点故障时,MMM/MHA套件可以立刻监控到,然后将服务自动切换到另一个主节点,继续提供服务,从而实现MySQL的高可用。这个方案的可用性可以达到99%。备注:MMM项目已于2012停止更新
  • DRBD通过底层的磁盘同步技术来解决数据同步的问题,就是RAID 1——把两台以上的主机的硬盘镜像成一个。这个方案不到3个9
  • Solaris Clustering/Oracle VM ,这个机制监控了包括硬件、操作系统、网络和数据库。这个方案一般会伴随着节点间的“心跳机制”,而且还会动用到SAN(Storage Area Network)或是本地的分布式存储系统,还会动用虚拟化技术来做虚拟机的迁移以降低宕机时间的概率。这个解决方案完全就是一个“全栈式的解决方案”。这个方案接近4个9
  • MySQL Cluster是官方的一个开源方案,其把MySQL的集群分成SQL Node 和Data Node,Data Node是一个自动化sharing和复制的集群NDB,为了更高的可用性,MySQL Cluster采用了“完全同步”的数据复制的机制来冗余数据结点。这个方案接近5个9

那么,这些2个9,3个9,4个9,5个9是什么意思呢?又是怎么来的呢?请往下看。

高可用性SLA的定义

重点来了,工业界有两种方法来测量SLA

  • 一个是故障发生到恢复的时间
  • 另一个是两次故障间的时间

通常我们采用前者,即故障发生到恢复的时间,也就是服务不可用时间

系统可用性 宕机时间/年 宕机时间/月 宕机时间/周 宕机时间/天
90% (1个9) 36.5 天 72 小时 16.8 小时 2.4 小时
99% (2个9) 3.65 天 7.20 小时 1.68 小时 14.4 分
99.9% (3个9) 8.76 小时 43.8 分 10.1 分钟 1.44 分
99.99% (4个9) 52.56 分 4.38 分 1.01 分钟 8.66 秒
99.999% (5个9) 5.26 分 25.9 秒 6.05 秒 0.87 秒

比如,99.999%的可用性,一年只能有5分半钟的服务不可用。感觉很难做到吧。
到 3 个 9 可以靠堆人,也就是 3 班倒之类的强制值班基本搞定。但是从 3 个 9 往上,就基本超出了人力的范畴,考验的是业务的自愈能力,架构的容灾、容错设计,灾备系统的完善等等。
据说Google 内部只有 4 个 9 以上的服务才会配备 SRE,SRE 是必须在接到报警 5 分钟之内上线处理问题的,否则报警系统自动升级到下一个 SRE。如果还没有,直接给老板发报警。

简而言之,SLA的几个9就是能持续提供可用服务的级别,不过,工业界中,会把服务不可用的因素分成两种:一种是有计划的,一种是无计划的。

无计划的

  • 系统级故障-包括主机、操作系统、中间件、数据库、网络、电源以及外围设备
  • 数据和中介的故障-包括人员误操作、硬盘故障、数据乱了
  • 外部因素-自然灾害、人为破坏、以及供电问题

有计划的

  • 日常任务-备份、容量规划、用户和安全管理,后台批处理应用
  • 运维相关-数据库维护、应用维护、中间件维护、操作系统维护、网络维护
  • 升级相关-数据库、应用、中间件、操作系统、网络、包括硬件升级

有计划的维护因素主要来自于变更管理,避免措施主要有以下几个方面:

  • 线下测试(Offline Test)
  • 灰度发布
  • 服务必须对回滚提供支持

针对回滚,跟大家分享一下,保证药到病除:

理由1:我这个数据改动之后格式跟以前的不兼容了,回退也不能正常!
秘籍1:设计、开发时候就考虑好兼容性问题!!!比如说数据库改字段的事就不要做,改成另加一个字段就好。数据存储格式就最好采用 protobuf 这种支持数据版本、支持前后兼容性的方案。最差的情况,也要在变更实施『之前』,想清楚数据兼容性的问题。没有回滚脚本,不给更新,起码做到有备而战。

理由2:我这个变更删掉东西了!回退之后数据也没了!
秘籍2:你一定是在逗我。把这个变更打回去,分成两半。第一半禁止访问这个数据。等到发布之后真没问题了,再来发布第二半,第二半真正删掉数据。这样第一半实施之后需要回滚还可以再回去。

理由3:我这个变更发布了之后, 其他依赖这个系统的人都拿到了错误的数据,再回退也没用了,他们不会再接受老数据了!
秘籍3:这种比较常见出现在配置管理、缓存等系统中。对这类问题,最重要的就是,应该开发一种跟版本无关的刷新机制。触发刷新的机制应该独立于发布过程。 要有一个强制刷新数据的手段。

以上三个秘籍覆盖了100%的回滚兼容性问题,如果有不存在的,请务必告诉我!

决定高可用的本质原因

通过上述影响SLA的因素,我们可以看出实现5个9意味着一年的时间只能有5分钟不可用,如果没有一支技术牛逼的团队加上一套自动化的工具,怎么能有高可用系统呢

要实现高可用系统,其中包括但不限于:

  • 软件的设计、编码、测试、上线和软件配置的水平
  • 工程师的技术水平
  • 运维的管理和技术水平
  • 数据中心的运营管理水平
  • 依赖于第三方服务的管理水平

ref
关于高可用的系统
来自 Google 的高可用架构理念与实践


您的鼓励是我写作最大的动力

俗话说,投资效率是最好的投资。 如果您感觉我的文章质量不错,读后收获很大,预计能为您提高 10% 的工作效率,不妨小额捐助我一下,让我有动力继续写出更多好文章。