【干货】阿里资深技术专家丁宇谈双11高可用架构演进之路

近日Velocity China 2016在京举行,会上阿里中间件技术部资深技术专家丁宇(花名叔同)发表了题为《零点之战–阿里双11高可用架构演进之路》的演讲。丁宇从2009年开始,参加了每年的阿里双11技术保障工作, 最近两年他分别以共享平台事业部双11项目负责人,和集团双11项目稳定性总负责人的身份参与其中。

阿里巴巴平台的业务规模在过去的8年呈指数级增长,给双11所带来的技术挑战是世界性的,特别是如何在零点峰值到来时确保系统的稳定性。零点技术挑战的本质是用有限的成本去实现最大化的集群整体吞吐能力和最佳的用户体验,并取得二者之间的平衡。阿里在解决这些问题的时候没有参考和借鉴的对象,只能自我创新。阿里技术团队在 8年双11历练中沉淀了很多技术产品,其中高可用方面的中间件技术,经历了几代架构的演进和优化越来越成熟,且在阿里双11技术保障中起到的作用越来越大。丁宇从扩展性、线上的容量规划、成本增速过快、精细化运行控制和线上稳定性治理等方面进行了阐述。

对于未来的挑战,丁宇则认为还有很多可以优化的地方,他归纳为精细化、数据化及智能化三方面,及从容量确定性到资源的确定性;更加精细化的分析和预测流量模型及业务模型;技术变量的采集、分析、预测,通过数据分析驱动,自主决策处理等,最终在用户体验、成本控制和最大系统吞吐能力之间找到新的平衡点。

演讲全文:

丁宇:大家好!我今天演讲的主题是《零点之战–阿里双11高可用架构演进之路》。大家知道,规模和场景是驱动技术发展的关键要素。阿里做了8年双11,业务规模有上百倍的增长,系统的复杂度和大促支撑难度更是以指数级攀升。随着规模的增加,技术挑战也非常不一样,后面会展开讲。这是一个世界级的场景,双11最难的就是保障零点峰值的稳定性,我们把它当做一场战争来打,是一场不能输的战争。面对世界级的难题,在业界没有什么可以参考和借鉴的对象,所以我们都是自主创新,沉淀了很多技术产品,高可用性的产品,经历了几代的架构演进,今天我会选取一部分跟大家做个交流。下面是我的个人介绍,和联系方式。

我们看一下整个双11的技术挑战是什么,大家知道做双11非常难,但是究竟难在什么地方?阿里内部有一句话:双11是业务的狂欢、技术的盛宴。阿里做了8年双11,这8年见证了电商业务的飞速发展,我们看一下业务指标变化。双11交易额从2009年的5.9亿到2016年,半个月以前的双11交易额达到1207亿,实现了200倍的增长。交易峰值从2009年的400笔每秒,到2016年17.5万笔每秒,增长了400多倍。系统规模也有几十倍、上百倍的增长。

在这一块面临着什么问题?首先面临的是系统扩展性的问题,规模增长了数百倍,系统是不是能水平扩展以支撑数百倍的增长?这是我们面临的首要难题。

双11零点技术挑战的本质是什么?是用较低的成本去实现最大化的吞吐量和最佳的用户体验,三者取得一个平衡,用合理的代价来解决零点峰值,支持好业务的狂欢,保证业务系统平稳运行。如果不限成本做这件事,难度会降低非常多。我们用有限成本来做这件事就会面临一个问题,集群规模、机器数、机房资源都是固定的,怎么能把资源最合理的分配下去?假设有500个系统,要一起来支持双11,要做一个非常极致的容量规划,把硬件资源能够非常均匀地分配给每一个应用,让整个集群整个技术链条上没有瓶颈,这就是容量领域最大的挑战。因为如果有一个地方存在短板,整个系统就没法做到最大化吞吐量,所以要求有一个极致的容量规划。

双11的不确定性来自于什么呢?还是来自于所有技术变量的叠加,如果业务不变,系统架构不变,技术也不升级,那难度会越来越小。但是所有事情都在变,好多变量,比如说用户的流量会发生很大的变化,有很大的增量,峰值流量的构成、还有系统架构的变化会带来很多不确定。流量的组成部分有哪些用户来源,哪些业务模型会让峰值的流量和压力不同。包括CPU利用率,这些会影响到整体,因为整个系统是在非常高的水位情况下运行的,又要运行平稳、整体全链条没有短板,所以对线上要实现非常精细化的运行控制,还要有很强大的稳定性治理能力,这又是一个挑战。

零点峰值对我们来说有什么意义?这个意义非常巨大。它可以让技术实现能力有个推动力,推动架构优化,加速技术演进和沉淀,催生技术创新,所以双11也是技术的盛宴。

针对这几个挑战,我今天分成几个部分:如何解决业务增长情况下扩展性的问题、如何解决线上容量规划的问题、如何解决成本增速很快的问题、如何做精细化的运行控制、如何治理线上稳定性。

先讲一下淘宝架构的发展背景,2007—2008年这两年,是从集中式架构快速演变为分布式的架构。大家已经非常熟悉这套架构,现在一般的互联网应用,互联网系统都会采用这样的分层架构,业务上分层,通过分布式中间件进行远程消息传递、远程服务调用,中间提供一层共享中心,把公共业务逻辑抽象成平台,抽象成服务中心,不直接对用户暴露接口,提供一种服务能力,中间会有缓存,底层有存储集群,这是非常常见的架构,在2008年整个架构演变到这个程度,到现在为止架构也没有发生太大变化。

随着场景的递增、体量的激增带来了很多别的问题,是这套架构不能解决的,后面会逐步展开。在这个演变的过程中,我们沉淀了大量的中间件技术产品,这里就像一个大厦,系统之间的交互,分布式环境下的交互,包括一致性协调、负载均衡工作都是由中间件完成的,中间件就相当于大厦的框架结构和管道,中间件的沉淀对后面的架构演进打了非常好的基础。

在这个架构改造完成后,早期双11的规模增长问题还没有那么明显,我们面临着很多其他问题,其中就包括系统可用性。因为我们由10个系统快速拆成100个系统,然后分层,水平拆分、垂直切分,面临着治理的问题。以前出现问题知道是一个系统导致的,可以快速回滚变更恢复,现在是100个系统,很难定位问题根源在哪里。好多系统发布、变更了,也没办法快速恢复,失去了先恢复后定位的能力,这是我们面临的挑战。当时存储层还有很多IOE技术组件,从2009年开始去IOE,存储这一层也把它升级成可以水平扩展的架构。

那个时候整个机房会遇到很多不稳定的情况,不知道有多少人当年也在做同样的事情,网络、电力都有不稳定的情况,很普遍,我们做 了同城容灾和异地冷备的架构迭代。同城两个机房,各承担50%的流量,数据库也放在两边一主一备。一个机房出问题的时候可以进行数据库、流量的切换,这是同城容灾的方案。

这套架构逐渐在双11碰到了很多问题,当规模增长的时候,对机房体量要求越来越大,要有很大的规模。分布式架构下,比如说A集群要对B集群有服务依赖调用,规模都是5千台,大家知道负载均衡的机制,需要建立连接。五千对五千,连接数在超级机房下是一个很大的挑战。数据库也一样,你规模达到了一万台,每台都要建立连接。单机房无法承载业务系统规模的增量,扩展性是在中间件这一层受到限制。

IDC的资源也存在限制,一个城市没有办法支撑我们的体量,这是物理限制。包括本地容灾问题,台风、电力导致问题,告诉你2小时后就拉闸限电,技术没准备好切换,业务就会受损。还有国际化部署的问题,需要把业务集群部署出去。这些挑战要求我们由同城走到异地。

我们去观察整个阿里电商的业务,它的数据模型,有这样一个方案。建设异地单元机房,在地域上可以相互容灾,异地大量调用的时延问题是一个巨大挑战。大家可以算一下,北京到上海调用一个RTT需要多少毫秒,一次调用可以接受,如果每个请求调用500次是绝对不能接受的。所以单元内要做调用封闭,必须在单元内完成所有的业务请求交互。同时要按用户的维度去切分单元流量,这样就可以实现水平扩展,什么规则的用户在哪个单元来处理他的业务请求。

我们分析整个阿里业务模型,分为买家数据、卖家数据,发现卖家数据体量适中,而且更新不那么频繁。买家数据会创建很多交易订单,数据规模和访问量很大,比卖家要大一个数量级。要保持每个单元的封闭,需要去切分买家集合,卖家数据集合小可以同步到各个单元,选择这样一个方案。在数据层实现数据同步,达到一致性,保证业务在单元内的封闭调用。

做完就是现在这么一个架构。可以按用户任意维度进行路由,运用不同规则路由到不同的单元机房,在单元内实现业务的闭环, 解决了请求时延的问题。后续扩展性就很好做了,容量不够再建一个单元,因为单元内闭环,所以可以建到更远的地方去,体量就不再是限制了。

每一层,每个单元都有完整的部署,当然也会有跨单元请求的情况存在,有一些服务调用、消息同步,包括底层的数据同步一直都在做,而且量很大,要保证每个单元的数据合法、一致,完成业务全链条的封闭。

这套架构对我们有什么帮助?首先它消除了IDC资源单点和容量单点的问题,容量瓶颈解决了,不会受地域的限制。也解决了异地容灾的问题,可以快速建一个单元,快速把流量切走。当一个地域性问题出现的时候,可以快速把流量切走,这个问题就恢复了,等地域性问题恢复,流量再切回来,日常可用性的保障就有了很好的提升。容量规划这件事也因此简化了,一个单元有固定的处理能力。然后可以快速复制一个单元,可以小体量验证,逐个单元批量复制,整体容量和扩展性就变得简单了。同时提升了可运维性,单元可以快速拉起、下线、迁移。这个问题的解决为后续的架构演进,打下了很好的基础。

看一下容量规划是怎么做的,这也经历了几个阶段的演进。一般来讲,要做容量一定要先掌握应用性能基线,比方说500个系统,每一个系统的性能基线都要掌握。最开始的时候,在线下开始做,使用很多常见的压测工具。当然受限于环境因素,线下环境很难打造一个完备的、跟线上非常相似的环境。我们通过压侧得到这个应用的性能基线,然后准备一个容量模型,通过基线吞吐量去计算将来有多大流量,在保持一定水位的前提下,可以知道在双11的时候应用怎么做容量规划。

这个计算模型好几年都没有变过,一直在变的一个事情是,如何测试这个应用的基线吞吐量能力。经历了几个阶段,线下是一个阶段,我们发现线下非常不准,然后又走到线上。如何使用线上环境不影响用户?得到一个高水位下的吞吐能力表现。采用线上引流的方式,无论存储层、服务层还是Web应用这一层,都是用线上引流,依赖于中间件,自研的中间件负载均衡,还有反向代理都有流量代理的能力。如果有一百台服务器,把其中80台的流量一点一点引到某10台上去,看在不同的流量压力下,系统负载的增加,用户响应时间的变化,三者之间的关系,把这张图画出来,这就比线下做这件事情精准度高很多,也逼近想要的结果,这就是我们线上压测的架构。我们评估出来基线能力然后做容量规划,这是一个阶段。

这个阶段很快就遇到了挑战,大家知道,早年在双11买东西时会遇到有一些大的、小的问题,跟容量规划不准有很大的关系。容量规划的目的是评估用户登陆、添加购物车、购买整个链条如何合理分配资源。刚才说一个应用双11加多少机器,根据对双11业务的理解来分配,这样做规划。这种流量规划是不是合理的?我们发现差距还是蛮大的,真正双11零点峰值的实际流量,与我们的规划差距比较大。

500多个核心系统,技术链条长、业务入口多、逻辑复杂,如果人来梳理难免会有各种各样的偏差。整个链条上瓶颈点比较多,因为没有验证过,问题会比较多。无法提前发现问题,双11峰值真正来的时候发现已经晚了,需要应急措施来处理这些问题。这个规划方法是堆积木的方法,拼出来整个集群配比,人的判断在里面起了很大的作用,往往都是不靠谱的。我们发现做容量规划不应该是一个一个应用系统去看,应该是一个业务链条整体去看。

如图所示,整个线上关系比这个复杂得多,这只是一个样例,上游调用方有十几二十个,下游依赖方有十几二十个,每个调用方轻微的差异变化就会对这个集群产生叠加效应,变化会放大,所以这个非常不准。我们缺乏验证整个链条实际承载能力的手段,这是遇到的很大的挑战。

我们提出需要一个验证方案,双11是属于有限场景,真正流量的冲击只在几个流量入口,可能是20个流量入口,整个洪峰流量关系是可以梳理出来的,每个链条一起来验证它的容量是不是符合预期,有这样一个方案设计。我们希望在线上来做,用大规模的流量去压测,从IDC到网络、中间件、应用、缓存、数据库,所有基础设施能够用同样的流量模型来验证,这也要求在线上做,而且要做海量请求,跟双11同样的流量验证整个集群的实际能力。

要自定义一个工具,业界所有的流量工具都满足不了规模的需求,所以要自己创造。同时业务模型和流量模型要非常精准,跟双11非常像,基于线上数据、测试数据结合构造一套特殊模型,大体量、大规模、非常逼真。如果字段是空的、假的,执行过程中对字段计算的消耗就是受限的、是不真实的,所以要达到非常严苛的拟真度。还要求在线上做读、写、创建、支付操作,同时绝对不能影响用户,压测数据、正常数据不能混在一起,用户要做到无感知。要把系统所有瓶颈暴露出来,我们设计了这样一个方案。

这里大量利用了之前沉淀的中间件体系。我们构造了一个分布式流量引擎,把它部署在全国阿里的CDN上,阿里CDN规模非常大,这满足了发出大流量的要求,可以反压阿里机房,产生巨大的压力,一秒达到上千万的QPS。在数据模型的构造上花了很大心思,每年会不断迭代,让它更加逼近真实。同时对用户的流量进行了很好的数据化分析,真正模拟双11当时的用户流量,结合这份数据推送到压测引擎里,然后从远端发起压力。

整个链条覆盖很长,和客户端一样建立链接,整个覆盖链条跟用户访问基本上是一样的。做的是线程级隔离,每个线程处理的可能是测试请求,也可能是正常用户请求,请求间互相无感知,数据不会共享。同时对数据存储层进行了隔离,也不会做全网的业务,只覆盖双11最重要的业务场景,这样风险比较可控,暴露问题也更加精准有针对性。

全链路压测是一个划时代的容量规划技术,压测演练过程中发现很多瓶颈,无论是容量调配问题、性能问题还是隐藏bug。并发的问题只有在大流量下才会暴露,小流量的线下测试,受限场景下是验不出来的,所以用这套方案,容量也可以调整,问题也可以暴露,我们每年用这个压测方案可以发现上千个问题,很多问题是非常致命的,如果双11的时候爆发都是不能承受的。

这个方案有什么意义,它打破了对于不可预知技术风险的控制能力,加速技术的进化。怎么理解?我们在短时间内可以大胆创新,大胆上新技术,更加激进。因为有一套保底方案,无论做多少创新,可以做到几个月升级一次架构,新技术几个月推到全网。因为双11要的是容量确定性,比如说要准备17.5万的能力,什么技术都可以尝试,最后通过线上演练,大流量全链路压测,看能不能达到17.5万。能达到技术是过关的,整体能力也是过关的,所以加速了技术的进化。

它能做到主动发现问题而不是被动等待,如果零点发现了再应急处理,应急处理往往是很被动的,而且容易忙中出错。应急出现的问题往往是预期不到,没有很好的手段去解决。比如说出现了数据问题, 写个脚本对数据做后台更新,这可能会产生更悲剧的事情,所以要减少应急的情况,尽量做到全都是确定的,有什么大招都是测试验证过的,这也是我们的经验。这种压测演练方式为我们稳定性的确定性打下了坚实的基础。

看一下成本优化,这是个很大的话题,我们可以做性能优化降低成本,但双11这个体量来讲,做单一系统优化对全局有多大帮助要打个问号,不是说它没有用。性能优化的关键还是在于找到瓶颈,对瓶颈进行优化,这个效果是最好的。胡子眉毛一把抓,500个系统都优化20%,最后不一定是整体水平提升20%,性能优化和降低成本也有一定的关系,然后可以进行架构整合,从架构层面做优化。通过分析,我们发现还有更好的方式。

上面的红线是日常处理能力,这是截取的某一段时间,几个月内的峰值情况。大家会发现,日常情况下很多小活动,日常能力是能够处理的,大活动日常能力是不能处理的。为了一个活动增加了一批机器资源,活动过后很长时间机器是没法利用起来的,要长期分摊这个成本,对双11来讲就是这样。为了双11这一天增加了大量成本,过后一年都会有资源利用率不高的情况,很可怕的浪费,因为体量比较大,低效运行对成本影响很大。需要找到一个能够帮助解决短时间内要很多资源,长时间又都不需要的问题,阿里云的弹性能力就是最好的方案,所以我们选择阿里云的基础设施,做混合云弹性架构。它可以降低资源保有时间,大促就一天,剩下时间就把资源归还给云,这个方案大幅降低了大促成本。我们做的混合云架构支撑双11,规模是全球最大的。使用云的效率高不高,资源保有时间长短很大程度上取决于运维能力,包括怎么跟业务集成,也做了很多运维能力的升级。包括8小时在云机房拉起一个站点,就是前面讲的8小时建一个单元,成本节约。以前是20天,现在提升到1天,对成本优化的效果是非常明显的。

买了一批资源建起一个站点,还需要把资源调匀,通过全链压测,3小时可以把整个机房甚至全部机房资源调匀,提升效率也是降低成本的手段。同时实施了全面Docker化,拉平异构平台的运维成本,用一年的时间把核心系统全部Docker化来支撑双11。做这种技术升级,是需要全链压测验证的,不然也不会这么快完成,现在阿里有几十万的Docker容器跑在线上。

接下来看一下运行控制,系统容量已经调匀,有了最大吞吐能力,但是用户热情很夸张,超出想象。超出整个集群处理能力的流量,需要把它挡在外面,如果放进来的话,整个集群就一起宕掉了,一个请求都处理不了,整体瘫痪,这时必须做限流保护和有损服务,放进来的流量好好处理,没有放进来的,等一会儿刷一下也会进来,这是通用做法。

我们通过访问请求数做限制,也可以通过应用负载做限制,也可以通过线程并发数。调用下游,当下游产生问题负载变高时,线程数会增加,这时就要对下游进行降级,要识别哪些系统可以被降级,系统自身可以自动完成降级,不会对核心业务产生大的影响,这是要事先识别的。通过识别哪些业务可以被降级,通过限流框架降掉这些场景。当发现流量大到无法处理时,就限制一些挡在外面,每一层都有限制,包括web接入层、应用层、服务层。整体原则是处理不了就别放进来,放进来的就是处理得了的,外面入口收紧一点,里面处理放松一点,有很多自我保护手段。

再看一下流量调度,整个系统在高水位运行的情况下很容易产生波动,有一个集群。平均来看整体水位70%,但是有几台可能濒临崩溃了,这很常见。比如说有一个比较大的计算,路由到某台机器,是经常碰到的。会发现很多流量也会同时路由到这台服务器,这些流量都会受到影响。根据实时探测,通过现有的一些基础能力、负载均衡进行流量调度,把有问题的机器归并在一起降权,有问题的计算就被隔离了,路由的流量就到了正常机器,分布式系统可以实现自我隔离和恢复,实现了流量的调度。关注局部用户体验,只要流量放进来,都要给一个比较好的处理和响应,提升整体的可用性和体验。

这是开关和预案,对双11来说非常重要。开关是系统后门,提供一套标准化的系统后门,可以让应用不改代码,通过配置改变行为,双11我们准备了非常多的开关。光有开关还不够,有些业务链条需要降级,可能一个链条上20个系统都要操作一些开关,才能把一个业务完整降级,在复杂系统上经常会遇到这样的场景。我们实现了一套预案体系,保证一系列的开关能有序、完整的被执行,而且每一台服务器都要执行到位,保证一致性、完整性。

一个经验教训就是双11的时候千万别执行没有测试过的开关,往往会出问题。双11今天体量很大,有数以千计的预案,还是对每一个预案进行测试,保证每一个开关、预案执行下去都是满足期望的。

下面说一下稳定性治理。当系统复杂到一定程度,没有一个人能掌握整个系统架构,只能用中间件能力来识别架构复杂度,理清关系。通过中间件的通道能力跟踪整个调用链条,推动架构梳理,整理出依赖关系,对海量调用进行统计,得到各个系统的稳定性指标,这都是从数据中挖掘的。比如说调用层次、响应时间,哪里阻断了会影响业务,哪里阻断了不会影响业务,都是被挖掘出来的。同时会结合业务测试用例看哪些链条可以被降级,哪些不可以降级,有些降下来主业务就不显示了。技术同学会对弱依赖做业务容错,强依赖要保证系统不能挂,稳定性治理非常关键。

做了这么多年双11,未来会有哪些挑战?我们希望能做到精细化、数据化、智能化的双11,从容量确定性到资源确定性,哪些应用放在一起,什么样的配置放在一起会让整体集群达到最佳状态,后续希望做到每一台物理机的内核怎么分配,仍然知道如何匹配达到最佳状态,进入到微观的层面,目的还是一样,让整体集群全局没有瓶颈,做到非常精细化。技术有很多变量,叠加会产生风险,所以要精细分析、预测,得出逼近真实的流量数据模型。我们希望做到智能化的双11,还是对这些变量,要通过数据分析去自我决策。根据多年的积累,系统对一些变量的变化区间是有容忍度的。一种是可以自我决策,降级是一种决策,一种是可以容忍变化。做到这样系统已经非常智能了,双11的时候不用做太多工作,大家可以看到曲线飙升,系统平稳运行,这是非常理想的。

同时随着体量继续增长,今天又迎来了一次技术升级的契机,所以希望在成本、体验和吞吐能力上继续探索,找到一个新的平衡点,能奉献给大家更完美的双11。谢谢大家!

Q & A

Q1:您上面提到的单元是怎么划分的?

丁宇:刚才讲到买家业务和卖家业务,会把完整的买家业务部署在每一个单元,买家系统有多少我们很清楚。卖家系统不需要部署,因为流量不会过来,只要梳理这些业务就可以了。但是阿里业务很复杂,林林总总,要看哪些系统属于这个域,我们有个标识,配置驱动,标识是单元应用,就知道新建站点的时候某些应用要跟着单元走,同时部署还有个顺序,跟着单元的建设一起走就可以。

Q2:一个完整的买家包括所有的服务做一个单元?

丁宇:对。

Q3:单元会有不同切换的情况在,那买家数据是怎么保持同步的?

丁宇:单元化的方案对用户流量来说比较简单,我们数据层做了非常多的工作,实时的把买家在这个单元产生的数据同步到中心,卖家数据要同步到单元,都要实时做。比如说发现1秒的延时,要等数据同步完成才能切换过来,数据同步效率非常关键。

Q4:如果再极端一点,是某个坏掉的单元变成完全不可访问的情况,这种产品怎么切换?

丁宇:这个数据是同步不出来的,这一块要做一个权衡,就是流量必须切走,这会产生数据不一致,可以事后补偿,要不然会产生更大的业务问题。