“这个世界上不可能存在一种 100% 稳定的系统”。
可以从两个方面进行解析,一方面故障是不可避免的,有人为的故障(人是容易出错的——Human Error)和非人为的故障(机器 Failure)。这些是无计划的停机,还有有计划的停机,如发布新系统、升级维护、更新硬件等。这也是为什么行业中即使部分公司做得再好也只能说自己能做到多少个 9,而非 100% 的主要原因。
当前,我们所能努力的就是尽可能地做到多少个 9,这其中需要很强的技术实力支撑。
级别 | 可用性级别 | 通俗说法 | 年度停机时间 | 配套措施 |
基本可用性 | 99% | 2 个 9 | 3d-15h-39m-29s | 服务在一个数据中心里有冗余,简单基础的自动化运维 |
高可用性 | 99.9% | 3 个 9 | 8h-45m-56s | 大量的自动化故障工具,以及各种控制调度系统等基础设施要做好 |
具有故障自动恢复 | 99.99% | 4 个 9 | 52m-35s | 本地多机房(像 AWS 一样每个地方都有三个可用区) |
极高可用性 | 99.999% | 5 个 9 | 5m-15s | 远程多机房,异地多活 |
另一方面,从分布式架构设计来说,我们认为这个世界上的软件都是有故障的,当故障发生时,大家无非都是希望两个事情:
- 故障不要蔓延开,能够控制得住;
- 故障的时间越短越好,不要太长。
然而,架构系统也有很多的依赖,如基础设施 DNS、CDN、运营商、机房等等,想要实现稳定,还需要大家一起来实现。
系统其实包括软件和硬件两个方面。
抛开一些人为的故意因素不谈,按照正常故障而言,宕机通常源于:
- 软件到达运行的瓶颈。常见的情况有:带宽占满或不足,对于不少公司而言,买够足够的带宽,需要花费高昂的费用,因此不少系统采用 CDN 技术,这样即使系统出现崩溃,但是网页都能打得开(比如 12306);还有应用的 CPU /内存过高,以及数据库或关键中间件处理不过来,有单点故障导致系统打不开等等。
- 工程能力的问题。造成这一问题的原因是上线前没有进行过相关的性能测试,亦或是企业内部没有扩容和应急计划,没有足够的运维工具和手段(如监控数据不足,没有足够的自动化的控制系统),不能快速解决问题。这就好像很多天灾一样,本质就是没有科学的管理,不重视技术,灾难来了后,才发现很多设计没有到位,甚至都是错的。
高并发没有一个具体的数字来衡量,但是跟业务逻辑和应用场景很有关系。
第一种是像 12306 系统、银行、电商等类似的业务场景,这些具备交易逻辑和复杂计算,有强一致性事务,这类的系统是最有挑战的系统,因此调优使用到的技术手段也是非常多的。从我个人经历来谈,2013 年,我在阿里巴巴做“双 11”时,交易业务使用到的服务器大约有 1500 台,当时是阿里第一次做全链路压力测试,性能设置在了每秒 5-8 万笔订单左右。经过几年下来,阿里最近的数据可以做到峰值每秒 60 万单,平时每秒 10 万单。除此之外,我经历过的饿了么系统在 2018 年时,一天有 3000 万笔订单,都集中在中午和晚上两个饭点,而且这是需要实时处理的订单,不过好在这个业务是地域性很强的业务,所以,很容易分库分表,做多活也相对比较容易。
第二种是像微博这样的社交类应用。相较前一种,这种应用通过没有太过复杂的交易逻辑,属于轻应用类,微博可以通过弹性扩容做到百万并发,普通社交类应用实现几万至几十万的 QPS(每秒查询率)也不算太难。这类的系统主要还是通过下面几种手段,一种是在各种环节加缓存,一种是通过异步和最终一致(这类系统基本不需要强一性,丢数据都无所谓),最后是通过 sharding 的方式把用户请求分布式。
第三种是像视频类的应用。像视频类就更简单了,不久前,刘德华的在线演唱会吸引了 3 亿人在线,虽然听起来数字非常庞大,但是从技术上来看,视频主要是广播和内容分发,基本没有交互逻辑。因此,用 CDN 这样的分发网络很容易实现几亿人同时在线。以世界杯比赛为例,全世界几十亿的人观看电视直播,这样的高并发早就实现了,因为主要是广播。
第四种是需要保证实时性的在线网游等应用,不过,在线网游通常是需要给玩家分区、分服务器的,这样一台服务只能处理有限的玩家,一般来说也就是几百个玩家,甚至更低。
整体而言,高并发与业务场景息息相关,在实现难易度上,偏交易型的第一种难度最高,其次是社交类,然后是游戏,最后是视频。所以,我们可以看到很多论文或是术语都会提到 transaction,transaction 通常意味着比较大的复杂度。
两种情况,一种是预期流量(像做活动),可以通过评估、压力测试,做好充足的事前准备。如阿里双 11,提前做好预案。
第二种是非预期的流量。以我曾在路透做金融数据为例,对于一些突发事件,会造成股票交易的高峰,倘若系统出现崩溃,是一件很可怕的事情。因此,平时做性能测试时,除了要高过平时流量来应对高峰,还需要考虑时常。比如平时的流量是 100K/s,那么性能测试时要做到 300K/s 以上。不过,这是有钱的做法。
如果没有钱的话,就要通过云计算的方式,实时扩容,微博就是这样做的,他们可以在 5 分钟内扩 1000 台服务器。最后,如果没有资源了,只能走最极端的手段,即拒绝用户访问,比如在阿里的双 11 就有这样的预案,如果量太大,就先停西部,再停中部,保中心城市和东部,不行就保北上广深等大城市。
这种预案在大公司非常常见,无论是国外的 Facebook、GitHub,还是国内的阿里、腾讯等,这样即使出现故障,造成的后续影响也会比一般公司好很多。
好的架构一定是设计出来的,而且还是精良设计的,不然就是系统集成了。
不过,软件设计也是一种 Trade-off (权衡)的取舍过程。随着公司不同时期的发展,不同的阶段有不同的重点,导致 Trade-off 也不一样,处于不断进化过程。因此,我认为这句话应该这么说,“一款好的软件必须是经过精良设计的,精良的设计是不断演化出来的”。
通用的维度分享:
- 首先要了解业务特性;
- 通过数据分析;
- 使用分布式的方式(业务用户数据流量分片或冗余、加缓存、降低一致性要求、异步系统等等);
- 不要魔改,要坚持功能高于性能,先做对、再做快的理念。