我的公众号「码农之屋」(id: Spider1818) ,分享的内容包括但不限于 Linux、网络、云计算虚拟化、容器Docker、OpenStack、Kubernetes、SDN、OVS、DPDK、Go、Python、C/C++编程技术等内容,欢迎大家关注。
1.背景介绍
2012年春节,铁道部推出12306网站,进行网络实名购票。每一个返乡人原以为不用再忍冻排队,就能买着一张回家的火车票,但结果还是大失所望。7天内,12306网站访问用户已占全球互联网用户的0.902%,每天点击量高达10亿人次;系统一度支撑不住如此庞大的访问量而陷入崩溃。针对12306的责难也不绝于耳。最近几年IT业内很热火,云计算、大数据以及Hadoop等概念铺天盖地袭来。针对12306遇到的难题,也就有诸如淘宝、人人网、即刻搜索以及Facebook等许多率先实践Hadoop的技术人员来分享应用经验。从表面看来,类似12306的高性能高并发系统与Facebook、微博以及淘宝节假日抢购活动非常类似,并且,淘宝、新浪以及Facebook等都在这一块做得非常的好。那么他们的经验是否可以借鉴呢?
以国际上非常流行的Facebook为例,Facebook的瞬间并发最大的特点就是写操作非常频繁,而Facebook的解决之道则在于通过利用HBase写速度快的特点来构建数据库,并对整个架构进行优化来达到缩短时间的目的,微博跟Facebook在本质上差不太多。而对于12306而言,其实质上应当属于频繁的混合读写操作,而且是小随机频繁读写,这在业内是公认的难题。与网游或QQ的后端负载相比,12306购票系统的压力显然要大得多。因为网游和QQ在线或是登录时访问的更多的是用户自己的数据,而订票系统访问的是中心的票量数据,这是不一样的。
12306互联网售票系统应该是一个高性能、高伸缩性、高可靠性的系统,可以在高峰期(例如春运时刻)增加机器能够应对高峰期的峰值用户群。而目前的传统做法是用一大堆好机器来做数据库集群和应用服务器集群,把用J2EE架构做出来的功能部署在应用服务器集群上,而把大部分压力都放在数据库上。传统的做法并不特别关注高性能、高可靠性、高伸缩性的应用架构设计、数据架构的设计和相应的代码质量。而这也正是12306系统所缺失的地方。
2.面临难题
通过公开数据可以看到铁路在春运期间是2.3亿人次,再按照出行高峰期来看也就是20天,也就是说每天的火车票数量可以近似的认为是近1000万张。如果我们的12306 系统是非常强悍(快、高效、稳定)的话,12306系统将会售出的票数为大部分(例如700万张),这样的话700万张票如果一放出来会被在几分钟内全部被抢完(如果按照人的习惯的话买一张票最好所费的时间是10分钟)。也就是说12306系统的处理能力是每秒能处理卖出(700万/(10分钟*60)=1.17万)张票,反映到事务的话更加恐怖。这种XTP(极限事务处理)处理能力如果按照一天八小时高峰运转的话就是3.36亿笔/天。所以,系统要具备高性能。
除了整个系统需要满足高性能需求之外,还得同时具备高可扩展性(高可伸缩性)。因为从历年来的经验来看,铁道部的并发高峰通常是在节假日发生,如五一、十一长假等,春运则是最大的一个并发高峰。而目前的情况看来,12306在线购票系统虽然不能应对春运高峰,但在平时售票却还是没有问题。这就使得这个系统必须具备高可伸缩性,在并发高峰来临之前,能够通过简单的加机器或者与新浪、淘宝、腾讯等大型互联网公司合作来共同应对这些并发高峰。
在具备上述两个特点的同时,还得具备高可靠性。这么大的并发单靠一台机器是不可能实现,必须采用集群来分散压力。而在集群中,必须防备机器故障,单台机器故障之后不能影响其他机器的正常运转,并且还必须在短时而将故障修复。
除了上述三大必备性能之外,如果想拥有更好的用户体验,那么还得具备一些其他的特点。目前移动互联网正飞速向前发展,各种智能移动终端(如智能手机、平板电脑)层出不穷,作为一个方便可行的系统,那么还应该对这些移动终端提供支持。另外,从现今角度除外,铁道部所售出的总票数是远远小于想要买票的人数的,供小于求,必然导致投机分子的存在,如“黄牛”,那么这个系统就还得作出一些措施来防范利用脚本、程序进行刷票的行为。刷票也是增加并发的一个因素之一,防止刷票也从另一个方面减少了并发,提高整个系统的可用性。
3.数据库设计
从用户操作角度来看,这个业务流程是非常清晰的。主要几个功能点就是:注册用户、查询余票信息、确认订票、支付票款、安全控制、取票。除了取票操作由用户到售票点/取票机器完成的话,其它的功能都在12306 互联网售票系统中实现。12306大致购票流程如图1所示。根据这些功能设计出来的12306系统的功能模块相对来说还是比较少的,然而就是由于功能逻辑上简单让很多实现人员对它比较轻视,使用传统的设计理念来应对,却没有预料到他在春运高峰期间所面临的并发压力是如此吓人,这种并发压力如此吓人到让应用系统性能急剧退化,导致现有的12306系统的问题。当然,功能模块的简单也给我们解决这么吓人的并发能力提供了可能。
其实,高并发性系统的瓶颈很大程度上决定于数据库的设计。目前购票系统的瓶颈,在于ACID的实现关键:锁。由于锁具有一定程度上的硬件独占性,以及过程串行化等特点,加上目前通用的数据库产品,会有内在的锁的升降级带来的开销。这种开销,再乘上国家级的业务量,就造成了,即使是使用目前性能最强的大型机,可能也扛不住这种对锁的使用需求。要真正解决这个系统中锁的问题,在数量级上提升锁效率,就目前来说,是不可能的,除非未来的计算机结构或部件发生革命性升级。
图1
我们还是可以做一些工作来缓解这种压力的。由于12306系统的数据库非常庞大,在信息交互的时候很容易出现问题。我可以把这些海量的数据进行分区,这样在就很大缓解了单一服务器的压力。我们可以把数据把某种逻辑来分类。比如火车票的订票系统可以按各铁路局来分,可按各种车型分,可以按始发站分,可以按目的地分,反正就是把一张表拆成多张有一样的字段但是不同种类的表,这样,这些表就可以存在不同的机器上以达到分担负载的目的。把火车票的数据分区,并放在各个省市,会对12306这个系统有非常有意义的质的性能的提高。
总的来说,对于数据库这个关键环节来说,我们得对数据库就行分割(分割方案如图2),对SQL语句进行查询优化。我们也都了解,关系数据库在多张表联合查询时常常崩溃,所以我们也要禁止这种查询。在硬件方面,要配置高性能的机器、大内存、SSD、高端存储。关系数据库集群(RAC/DB2 Purescale),特别是DB2 PureScale的公开资料证明它能线性扩展到几百个节点。
图2
由于我们要对数据进行分割,所以数据库集群方案选择Share-Nothing架构中,其每一个节点都拥有自己的内存和存储,都保留数据的完整副本。可负载均衡的Share-Nothing架构的好处是每台服务器都能提供服务,能充分利用现有资源,达到更高的吞吐量。所以,选择这种架构可以承担起12306的高并发访问。
图3 Share-Nothing架构
4.体系结构
我们知道在售票高峰期,由于火车票的超高性价比和相应的方便性,每一张火车票都是稀缺资源和紧俏商品。所以几百万、上千万甚至更多的人像洪水一样在12306互联网售票系统开售的时候,疯狂地涌入系统中进行点击以买到票。当12306每天开门迎客的时候突然涌上几百万、上千万甚至跟多压到12306系统上进行抢票,但是由于12306现有应用的问题导致很多人根本登录不进入,并且登录进去的人查询余票和订票、支付的时候也奇慢无比。而登录不进去的人就在网页上徘徊不断的点击以等待到登录成功所带来的喜悦、甚至很多人通过机器人来进行登录、查询余票、订票等操作;这样其实就更加增加了无谓的压力导致PV量疯狂上升,一整天(凌晨六点到晚上22点)都是高峰期。很多问题都是由于12306现有应用的问题才产生的。
4.1现行系统架构设想
传统的设计此类系统的理念是:
由于使用传统的思维进行12306系统的设计,这样也就带来了各种问题。由于没有公开的12306系统设计资料,如图4所示是根据系统功能猜想处理的系统架构示意图。
图4
这种架构的应用系统,如果使用好的硬件设施(大内存、SSD、高速网络(例如万兆网/Infiniband网络),代码质量优良的话、调优(例如数据库调优,硬件调整,操作系统调优,中间件调优)做的好的话,以及有较好的技术人力资源的话,应对几十万级别的并发用户应该还是能够应对自如的。但是现在12306系统在春运及节假日高峰期所面临的挑战是几百万级别的并发甚至上千万的并发(个人所产生的压力和大量机器人模拟产生的压力),不对这种传统的应用架构和数据架构进行优化的话将无法应对。即使进行各种优化,由于这种系统架构本身的局限性,系统在峰值时刻的并发压力太大了,依然导致12306互联网售票系统的设计和实现将会非常的复杂。
4.2新的系统架构
为了设计新的架构,先做出以下假设:
由前面的论述我们可以知道,12306网站在大部分时候都是可以正常运行的,只是在春运期间和节假日时期有海量的用户登录,这样也就给系统带来了很大的压力,也就导致了各种问题。所以,对于大并发量的用户核心业务应用系统,可伸缩性是生死交关的问题。在一个可伸缩的架构中,资源的消耗应该随负载线性(或更佳)上升,负载可由用户流量、数据量等测量。如果说性能衡量的是每一工作单元所需的资源消耗,可伸缩性则是衡量当工作单元的数量或尺寸增加时,资源消耗的变化情况。并且我们要达到以下几点:
既然把最主要的数据库问题解决了,那么新的12306体系结构可以如图5所示。
图5
4.网络布局方案及核心硬件设备
关于互联网络的分类方案,主要有直接互联网络和间接互联网络两种拓扑形式,其中,直接网络又称为静态网络或者基于路由的网络,间接网络又称为动态网路或者基于交叉开关矩阵的网络,间接网络不适合当前分布式的发展方向,直连网络中的节点互相直接相连,每一个节点都是具有完整路由器功能的自治系统,控制简单,便于分布式管理,具有良好的可扩展性,且随着系统中节点数目的增多,直接网络的通信带宽、存储器资源和计算能力也同时相应增加,所以适合构造大规模并行计算机。
由于12306访问量的巨大,所以要保证足够的带宽来交换信息。而现在万兆以太网已经是主流配置,所以,对于12306来说也应该选择万兆以太网。为了响应去IOE化,我选择华为作为解决方案提供商。具体逻辑图如图5所示。华为CE12800/S9700/S7700/S5700万兆系列交换机 具有设备级可靠、链路级可靠、网络级可靠和面向应用级可靠:
• 设备级可靠:电源和风扇等关键部件冗余,核心和 汇聚交换机支持主控冗余和不间断转发(NSF)/优雅重 启(GR)等技术;
• 链路级可靠:华为独有的网络保护技术SEP、维护 和管理(OAM,业界唯一硬件实现)和双向转发检测(BFD,业界唯一硬件实现)等功能;
• 网络级可靠:IGP路由协议、IP快速路由等;
• 面向应用级可靠:智能路由、链路质量探测(NQA)等。
图6
硬件设备:
NetEngine40E系列全业务路由器(以下简称 NE40E)是华为公司推出的高端网络产品,主要应用在企业广域网核心节点、大型企业接入节点、园区互联&汇聚节点以及其他各种大型IDC网络的边缘位置,与NE5000E骨干路由器、NE20E汇聚路由器产品配合组网,形成结构完整、层次清晰的IP网络解决方案。
CE12800系列交换机是华为公司面向数据中心和高端园区网络推出的新一代高性能核心交换机。CE12800系列采用先进的硬件架构设计,是目前全球最高配置的核心交换机。整机最大支持64Tbps交换容量,最高支持192个100GE、384个40GE或1536个10GE全线速接口。两台交换机应该满足需要。需要四台。
S7700系列是华为公司面向下一代企业网络架构而推出的新一代高端智能路由交换机。其性能大致为:100GE Ready;480个万兆端口,24个40GE端口;创新的CSS交换网集群;硬件级以太OAM/BFD;左后风道,高密布线。S5700系列全千兆企业交换机(以下简称S5700),它基于高性能硬件芯片和华为公司统一的VRP软件平台,具备大容量、高密度千兆端口,可提供万兆上行,充分满足企业用户的园区网接入、汇聚、IDC千兆接入以及千兆到桌面等多种应用场景。具有下列这些特点:创新AHM节能;智能iStack,支持9台设备堆叠;硬件级以太OAM/BFD;高性能Netstream;双电源可靠供电。
5.负载均衡、缓存与前端优化
5.1负载均衡
数据分区可以在一定程度上减轻负载,但是无法减轻热销商品的负载,对于火车票来说,可以认为是大城市的某些主干线上的车票。这就需要使用数据镜像来减轻负载。使用数据镜像,你必然要使用负载均衡,在后端,我们可能很难使用像路由器上的负载均衡器,因为那是均衡流量的,因为流量并不代表服务器的繁忙程度。因此,我们需要一个任务分配系统,其还能监控各个服务器的负载情况。
图7
5.2数据库缓存
负载均衡系统解决了资源的分配问题,但仅仅做到这些还不够。为了减少时延和数据库交互次数,我们可以我们还应该为数据库集群系统前加入缓存环节。缓存分为文件缓存、内存缓存、数据库缓存。在大型Web应用中使用最多且效率最高的是内存缓存。最常用的内存缓存工具是Memcached。使用正确的缓存系统可以达到实现以下目标:使用缓存系统可以提高访问效率,提高服务器吞吐能力,改善用户体验;减轻对数据库及存储集服务器的访问压力;Memcached服务器有多台,避免单点故障,提供高可靠性和可扩展性,提高性能。如图8所示。
图8
5.3前端优化
如果不对前端进行优化的话,少量用户访问系统影响不是很大。但对于12306系统来说,其访问量是巨大的,不进行优化的话势必会造成时延、崩溃等问题。对于前端优化,有很多方法,比如减少CSS文件,减少DOM操作等。通过前端优化,可以减少http请求次数、减少时延、减少数据交互量,这样很大的缓解了服务器的压力。
6.作业调度与系统管理
根据一定的数据库分割规则,我们对数据库进行了分割,即使如此还是会给系统带来很大的负担,我们需要对服务器进行分布式布局,把服务器按照地理位置进行布局,这样就可以使用户访问就近的服务器完成购票流程。这也就对用户进行了分流,但怎么对任务进行调度也是一个值得思索的问题。
HPC集群是一组通过网络连接的高性能服务器(或者PC服务器)的松散耦合,这些服务器通过并行计算的方式来解决单台服务器无法满足的复杂计算问题,具有较高的性价比。作业调度系统主要负责接收用户提交的作业请求,并根据特定的调度规则以及用户对作业的要求选择合适的计算资源来完成用户作业。在作业调度系统的帮助下,对用户而言高性能计算集群系统就好像一台具备很多CPU的大服务器,多个用户可以同时使用这个系统。作业调度系统管理用户提交的作业,为各个作业合理地分配资源,从而确保充分利用集群系统的计算能力,并尽可能迅速地得到运算结果。
集群作业调度管理可以根据用户的需求,动态地完成集群的软硬件资源的管理和调度,保证用户作业公平合理地共享集群资源,提高系统利用率和吞吐率。
具体关于作业调度方法的选择,作业调度策略对大型计算机系统的利用率影响极大,根据老师上课所讲的作业调度算法为本系统选择了以Backfiling算法为主的作业调度策略。Backfiling算法即“回填算法”,允许为大作业预留资源,然后充分利用作业预约过程中产生的时间间隙,让作业等待队列中的小作业跳过预约资源的大作业,优先调度使其在大作业之前执行,这样不仅避免了大作业的饥饿现象,提高了小作业的相应时间,而且增加了系统的资源利用率。由于Backfiling算法更加有效地利用了系统的资源。提高了系统的吞吐率,故方案效仿曙光集群系统中的Backfiling调度策略。
国家智能中心开发的曙光超级服务器作业管理系统 JMS 中采用了RB-FIFT 调度算法。该算法是由中国科学院计算技术研究所的梁毅、孟丹等人提出的,它是一种结合FirstFit 和预约回填机制的算法。在 JMS 中,采用FirstFit 的调度方式,同时为每个作业设定优先级,作业优先级随着其在作业队列中被调度次数的增加而增大,当优先级增大至一定阈值时,该作业将阻塞队列中后面作业的调度,直至其所需的资源得到满足。优先级阈值的设定,解决了作业饥饿问题,但是当作业优先级达到阈值却仍无法获得足够资源时,它阻塞后面作业的运行,系统中的空闲资源处于闲置状态,这就造成了资源碎片。梁毅、孟丹等提出了RB-FIFT 算法解决了此问题。RB-FIFT 就是结合FirstFit 的预约回填算法,当作业的优先级达到阈值时,对其所需的节点资源预约,对于预约产生的资源碎片,该算法计算出资源空闲周期,然后从作业队列中选取作业估计执行时间小于该空闲周期的作业插入空闲周期运行,从而有效地利用了系统资源。
图9
作为高速运转的大型分布并行计算机,合理有效的系统管理是保证计算机系统正常运行的关键。首先计算机系统管理人员的工作至关重要,应该具备服务器、网络设备、数据库、操作系统、应用软件、计算机安全等维护技能,具备较强的故障以及应急处理能力。为了保证节点7*24小时在线,保证应用系统资源的正常运行,计算机系统管理维护人员必须保证5*8或者7*24个人通信的畅通以及两小时到达现场的能力。
本系统采用目前市面上使用的高性能计算机的监控工具对整个集群系统的软硬件运行状态进行实时监控,如:整个系统工作环境,各节点CPU和内存的使用率,网络流量,各节点主板温度、CPU温度,机箱风扇转速、CPU风扇转速,主板电压、CPU电压等等,使系统管理员对各节点的情况一目了然。在分布式服务器管理系统软件中有一些比较优秀的软件,其中比较理想的一个是Cfengine。它可以对服务器进行分组,不同的分组可以分别定制 系统配置文件、计划任务等配置。它是基于C/S 结构的,所有的服务器配置和管理脚本程序都保存在Cfengine Server上,而被管理的服务器运行着 Cfengine Client 程序,Cfengine Client通过SSL加密的连接定期的向服务器端发送请求以获取最新的配置文件和管理命令、脚本程序、补丁安装等任务。有了Cfengine这种集中式的服务器管理工具,我们就可以高效的实现大规模的服务器集群管理,被管理服务器和 Cfengine Server 可以分布在任何位置,只要网络可以连通就能实现快速自动化的管理。所以,通过这种系统管理服务器我们就可以完成对系统的管理,使系统可以高效的工作。
7.总结
通过对12306面临问题的论述,本方案对其最大的制约瓶颈数据的架构进行了新的集群设计,提出了具有高并发能力的系统框架。为了更好的满足海量用户的需求,还对数据库增加了缓存及前端优化。经过高效的作业调度和系统管理,我们就可以处理高并发任务,合理的分配资源,使用户顺利的完成购票流程。
在本方案中,最关键的就是数据库集群的设计,因为大部分高并发网站系统的制约瓶颈就是数据库,鉴于购票系统的特点,本方案把数据库进行了分割,以求更好的完成任务,还对数据库进行了分布式布局,这样就能对高峰期用户进行导流,大大缓解了系统的压力。而且,由于对数据库进行了缓存,那么高访问率的数据就不用再进行数据库查询,直接就可以从缓存中读取,这也大大减少了服务器的工作量。总的来说,本方案可以较好的解决12306系统的高并发性问题。
数据冰冷的,但我们要让数据温暖起来,改变我们的生活!
我的公众号「码农之屋」(id: Spider1818) ,分享的内容包括但不限于 Linux、网络、云计算虚拟化、容器Docker、OpenStack、Kubernetes、SDN、OVS、DPDK、Go、Python、C/C++编程技术等内容,欢迎大家关注。