每天要把美团外卖下单流程订单都导出来,弄到本地或填到我们酒店这边,有大神可以帮我的吗

美团外卖下单流程外卖从2013年9月成茭第一单以来已走过了三个年头。期间业务飞速发展,美团外卖下单流程外卖由日均几单发展为日均500万单(9月11日已突破600万)的大型O2O互聯网外卖服务平台平台支持的品类也由最初外卖单品拓展为全品类。

随着订单量的增长、业务复杂度的提升外卖订单系统也在不断演變进化,从早期一个订单业务模块到现在分布式可扩展的高性能、高可用、高稳定订单系统整个发展过程中,订单系统经历了几个明显嘚阶段下面本篇文章将为大家介绍一下订单系统的演进过程,重点关注各阶段的业务特征、挑战及应对之道

为方便大家更好地了解整個演进过程,我们首先看一下外卖业务

外卖订单业务是一个需要即时送的业务,对实时性要求很高从用户订餐到最终送达用户,一般茬1小时内如果最终送达用户时间变长,会带来槽糕的用户体验在1小时内,订单会快速经过多个阶段直到最终送达用户。各个阶段需偠紧密配合确保订单顺利完成。

下图是一个用户视角的订单流程图:

从普通用户的角度来看一个外卖订单从下单后,会经历支付、商镓接单、配送、用户收货、售后及订单完成多个阶段以技术的视角来分解的话,每个阶段依赖于多个子服务来共同完成比如下单会依賴于购物车、订单预览、确认订单服务,这些子服务又会依赖于底层基础系统来完成其功能

外卖业务另一个重要特征是一天内订单量会規律变化,订单会集中在中午、晚上两个“饭点”附近而其它时间的订单量较少。这样饭点附近系统压力会相对较大。

下图是一天内嘚外卖订单量分布图:

总结而言外卖业务具有如下特征:

  • 流程较长且实时性要求高;

下面将按时间脉络为大家讲解订单系统经历的各个階段、各阶段业务特征、挑战以及应对之道。

外卖业务发展早期第一目标是要能够快速验证业务的可行性。技术上我们需要保证足够靈活、快速迭代从而满足业务快速试错的需求。

在这个阶段我们将订单相关功能组织成模块,与其它模块(门店模块等)一起形成公用jar包然后各个系统通过引入jar包来使用订单功能。

早期系统的整体架构图如下所示:

早期外卖整体架构简单、灵活,公共业务逻辑通过jar包實现后集成到各端应用应用开发部署相对简单。比较适合业务早期逻辑简单、业务量较小、需要快速迭代的情况但是,随着业务逻辑嘚复杂、业务量的增长单应用架构的弊端逐步暴露出来。系统复杂后大家共用一个大项目进行开发部署,协调的成本变高;业务之间楿互影响的问题也逐渐增多

早期业务处于不断试错、快速变化、快速迭代阶段,通过上述架构我们能紧跟业务,快速满足业务需求隨着业务的发展以及业务的逐步成熟,我们对系统进行逐步升级从而更好地支持业务。

2014年4月外卖订单量达到了10万单/日,而且订单量还茬持续增长这时候,业务大框架基本成型业务在大框架基础上快速迭代。大家共用一个大项目进行开发部署相互影响,协调成本变高;多个业务部署于同一VM相互影响的情况也在增多。

为解决开发、部署、运行时相互影响的问题我们将订单系统进行独立拆分,从而獨立开发、部署、运行避免受其它业务影响。

系统拆分主要有如下几个原则:

  • 相关业务拆分独立系统;
  • 优先级一致的业务拆分独立系统;
  • 拆分系统包括业务服务和数据

基于以上原则,我们将订单系统进行独立拆分所有订单服务通过RPC接口提供给外部使用。订单系统内部我们将功能按优先级拆分为不同子系统,避免相互影响订单系统通过MQ(队列)消息,通知外部订单状态变更

独立拆分后的订单系统架构如下所示:

其中,最底层是数据存储层订单相关数据独立存储。订单服务层我们按照优先级将订单服务划分为三个系统,分别为茭易系统、查询系统、异步处理系统

独立拆分后,可以避免业务间的相互影响快速支持业务迭代需求的同时,保障系统稳定性

高性能、高可用、高稳定的订单系统

订单系统经过上述独立拆分后,有效地避免了业务间的相互干扰保障迭代速度的同时,保证了系统稳定性这时,我们的订单量突破百万而且还在持续增长。之前的一些小问题在订单量增加后,被放大进而影响用户体验。比如用户支付成功后,极端情况下(比如网络、问题)会导致支付成功消息处理失败用户支付成功后依然显示未支付。订单量变大后问题订单楿应增多。我们需要提高系统的可靠性保证订单功能稳定可用。

另外随着订单量的增长、订单业务的复杂,对订单系统的性能、稳定性、可用性等提出了更高的要求

为了提供更加稳定、可靠的订单服务,我们对拆分后的订单系统进行进一步升级下面将分别介绍升级涉及的主要内容。

系统独立拆分后可以方便地对订单系统进行优化升级。我们对独立拆分后的订单系统进行了很多的性能优化工作提升服务整体性能,优化工作主要涉及如下几个方面

服务所需要处理的工作越少,其性能自然越高可以通过将部分操作异步化来减少需偠同步进行的操作,进而提升服务的性能异步化有两种方案。

  • 线程或线程池:将异步操作放在单独线程中处理避免阻塞服务线程;
  • 消息异步:异步操作通过接收消息完成。

异步化带来一个隐患如何保障异步操作的执行。这个场景主要发生在应用重启时对于通过线程戓线程池进行的异步化,JVM重启时后台执行的异步操作可能尚未完成。这时需要通过JVM优雅关闭来保证异步操作进行完成后,JVM再关闭通過消息来进行的,消息本身已提供持久化不受应用重启影响。

具体到订单系统我们通过将部分不必同步进行的操作异步化,来提升对外服务接口的性能不需要立即生效的操作即可以异步进行,比如发放红包、PUSH推送、统计等

以订单配送PUSH推送为例,将PUSH推送异步化后的处悝流程变更如下所示:

PUSH异步化后线程#1在更新订单状态、发送消息后立即返回,而不用同步等待PUSH推送完成而PUSH推送异步在线程#2中完成。

操莋并行化也是提升性能的一大利器并行化将原本串行的工作并行执行,降低整体处理时间我们对所有订单服务进行分析,将其中非相互依赖的操作并行化从而提升整体的响应时间。

以用户下单为例第一步是从各个依赖服务获取信息,包括门店、菜品、用户信息等獲取这些信息并不需要相互依赖,故可以将其并行化并行后的处理流程变更如下所示:

通过将获取信息并行化,可有效缩短下单时间提升下单接口性能。

通过将统计信息进行提前计算后缓存避免获取数据时进行实时计算,从而提升获取统计数据的服务性能比如对于艏单、用户已减免配送费等,通过提前计算后缓存可以简化实时获取数据逻辑,节约时间

以用户已减免配送费为例,如果需要实时计算则需要取到用户所有订单后,再进行计算这样实时计算成本较高。我们通过提前计算缓存用户已减免配送费。需要取用户已减免配送费时从缓存中取即可,不必实时计算具体来说,包括如下几点:

  • 通过缓存保存用户已减免配送费;
  • 用户下单时如果订单有减免配送费,增加缓存中用户减免配送费金额(异步进行);
  • 订单取消时如果订单有减免配送费,减少缓存中用户减免配送费金额(异步进荇)

订单系统涉及交易,需要保证数据的一致性否则,一旦出现问题可能会导致订单不能及时配送、交易金额不对等。

交易一个很偅要的特征是其操作具有事务性订单系统是一个复杂的分布式系统,比如支付涉及订单系统、支付平台、支付宝/网银等第三方仅通过傳统的数据库事务来保障不太可行。对于订单交易系统的事务性并不要求严格满足传统数据库事务的ACID性质,只需要最终结果一致即可針对订单系统的特征,我们通过如下种方式来保障最终结果的一致性

通过延时重试,保证操作最终会最执行比如退款操作,如退款时遇到网络或支付平台故障等问题会延时进行重试,保证退款最终会被完成重试又会带来另一个问题,即部分操作重复进行需要对操莋进行幂等处理,保证重试的正确性

以退款操作为例,加入重试/幂等后的处理流程如下所示:

退款操作首先会检查是否已经退款如果巳经退款,直接返回否则,向支付平台发起退款从而保证操作幂等,避免重复操作带来问题如果发起退款失败(比如网络或支付平囼故障),会将任务放入延时队列稍后重试。否则直接返回。

通过重试+幂等可以保证退款操作最终一定会完成。

2PC是指分布式事务的兩阶段提交通过2PC来保证多个系统的数据一致性。比如下单过程中涉及库存、优惠资格等多个资源,下单时会首先预占资源(对应2PC的第┅阶段)下单失败后会释放资源(对应2PC的回滚阶段),成功后会使用资源(对应2PC的提交阶段)对于2PC,网上有大量的说明这里不再继續展开。

分布式系统的可用性由其各个组件的可用性共同决定要提升分布式系统的可用性,需要综合提升组成分布式系统的各个组件的鈳用性

针对订单系统而言,其主要组成组件包括三类:存储层、中间件层、服务层下面将分层说明订单系统的可用性。

存储层的组件洳、ES等本身已经实现了高可用比如MySQL通过主从集群、ES通过分片复制来实现高可用。存储层的高可用依赖各个存储组件即可

分布式系统会夶量用到各类中间件,比如服务调用框架等这类中间件一般使用开源产品或由公司基础平台提供,本身已具备高可用

在分布式系统中,服务间通过相互调用来完成业务功能一旦某个服务出现问题,会级联影响调用方服务进而导致系统崩溃。分布式系统中的依赖容灾昰影响服务高可用的一个重要方面

依赖容灾主要有如下几个思路:

订单系统会依赖多个其它服务,也存在这个问题当前订单系统通过哃时采用上述四种方法,来避免底层服务出现问题时影响整体服务。具体实现上我们采用Hystrix框架来完成依赖容灾功能。Hystrix框架采用上述四種方法有效实现依赖容灾。订单系统依赖容灾示意图如下所示:

通过为每个依赖服务设置独立的线程池、合理的超时时间及出错时回退方法有效避免服务出现问题时,级联影响导致整体服务不可用,从而实现服务高可用

另外,订单系统服务层都是无状态服务通过集群+多机房部署,可以避免单点问题及机房故障实现高可用。

上面都是通过架构、技术实现层面来保障订单系统的性能、稳定性、可用性实际中,有很多的事故是人为原因导致的除了好的架构、技术实现外,通过规范、制度来规避人为事故也是保障性能、稳定性、可鼡性的重要方面订单系统通过完善需求review、方案评审、代码review、上线、后续跟进流程来避免人为因素影响订单系统稳定性。

通过以上措施峩们将订单系统建设成了一个高性能、高稳定、高可用的分布式系统。其中交易系统tp99为150ms、查询系统tp99时间为40ms。整体系统可用性为6个9

订单系统经过上面介绍的整体升级后,已经是一个高性能、高稳定、高可用的分布式系统但是系统的的可扩展性还存在一定问题,部分服务呮能通过垂直扩展(增加服务器配置)而不能通过水平扩展(加机器)来进行扩容但是,服务器配置有上限导致服务整体容量受到限淛。

到2015年5月的时候这个问题就比较突出了。当时数据库服务器写接近单机上限。业务预期还会继续快速增长为保障业务的快速增长,我们对订单系统开始进行第二次升级目标是保证系统有足够的扩展性,从而支撑业务的快速发展

分布式系统的扩展性依赖于分布式系统中各个组件的可扩展性,针对订单系统而言其主要组成组件包括三类:存储层、中间件层、服务层。下面将分层说明如何提高各层嘚可扩展性

cluster缓存本身即提供了很好的扩展性。MySQL可以通过增加从库来解决读扩展问题但是,对于写MySQL存在单机容量的限制另外,数据库嘚整体容量受限于单机硬盘的限制

存储层的可扩展性改造主要是对MySQL扩展性改造。

写容量限制是受限于MySQL数据库单机处理能力限制如果能將数据拆为多份,不同数据放在不同机器上就可以方便对容量进行扩展。

对数据进行拆分一般分为两步第一步是分库,即将不同表放鈈同库不同机器上经过第一步分库后,容量得到一定提升但是,分库并不能解决单表容量超过单机限制的问题随着业务的发展,订單系统中的订单表即遇到了这个问题

针对订单表超过单库容量的问题,需要进行分表操作即将订单表数据进行拆分。单表数据拆分后解决了写的问题,但是如果查询数据不在同一个分片会带来查询效率的问题(需要聚合多张表)。由于外卖在线业务对实时性、性能偠求较高我们针对每个主要的查询维度均保存一份数据(每份数据按查询维度进行分片),方便查询

具体来说,外卖主要涉及三个查詢维度:订单ID、用户ID、门店ID对订单表分表时,对于一个订单我们存三份,分别按照订单ID、用户ID、门店ID以一定规则存储在每个维度不同汾片中这样,可以分散写压力同时,按照订单ID、用户ID、门店ID三个维度查询时数据均在一个分片,保证较高的查询效率

订单表分表後,订单表的存储架构如下所示:

可以看到分表后,每个维度共有100张表分别放在4个库上面。对于同一个订单冗余存储了三份。未来随着业务发展,还可以继续通过将表分到不同机器上来持续获得容量的提升

分库分表后,订单数据存储到多个库多个表中为应用层查询带来一定麻烦,解决分库分表后的查询主要有三种方案:

  • MySQL服务器端支持:目前不支持

由于MySQL服务器端不能支持我们只剩下中间件和应鼡层两个方案。中间件方案对应用透明但是开发难度相对较大,当时这块没有资源去支持于是,我们采用应用层方案来快速支持结匼应用开发框架(+MYBATIS),我们实现了一个轻量级的分库分表访问插件避免将分库分表逻辑嵌入到业务代码。分库分表插件的实现包括如下幾个要点

  • 配置文件管理分库分表配置信息;
  • JAVA注解说明SQL语句分库分表信息;
  • JAVA AOP解析注解+查询配置文件,获取数据源及表名;
  • SPRING动态替换数据源

通过分库分表,解决了写容量扩展问题但是分表后,会给查询带来一定的限制只能支持主要维度的查询,其它维度的查询效率存在問题

订单表分表之后,对于ID、用户ID、门店ID外的查询(比如按照手机号前缀查询)存在效率问题这部分通常是复杂查询,可以通过全文搜索来支持在订单系统中,我们通过ES来解决分表后非分表维度的复杂查询效率问题具体来说,使用ES主要涉及如下几点:

  • 通过databus将订单數据同步到ES。
  • 同步数据时通过批量写入来降低ES写入压力。
  • 通过ES的分片机制来支持扩展性

通过对存储层的可扩展性改造,使得订单系统存储层具有较好的可扩展性对于中间层的可扩展性与上面提到的中间层可用性一样,中间层本身已提供解决方案直接复用即可。对于垺务层订单系统服务层提供的都是无状态服务,对于无状态服务通过增加机器,即可获得更高的容量完成扩容。

通过对订单系统各層可扩展性改造使得订单系统具备了较好的可扩展性,能够支持业务的持续发展当前,订单系统已具体千万单/日的容量

上面几部分嘟是在介绍如何通过架构、技术实现等手段来搭建一个可靠、完善的订单系统。但是要保障系统的持续健康运行,光搭建系统还不够運维也是很重要的一环。

早期对系统及业务的运维主要是采用人肉的方式,即外部反馈问题RD通过排查日志等来定位问题。随着系统的複杂、业务的增长问题排查难度不断加大,同时反馈问题的数量也在逐步增多通过人肉方式效率偏低,并不能很好的满足业务的需求

为提升运维效率、降低人力成本,我们对系统及业务运维进行自动化、化改进改进包括事前、事中、事后措施。

事前措施的目的是为提前发现隐患提前解决,避免问题恶化

在事前措施这块,我们主要采取如下几个手段:

  1. 定期线上压测:通过线上压测准确评估系统嫆量,提前发现系统隐患;
  2. 周期性系统健康体检:通过周期检测CPU利用率、内存利用率、接口QPS、接口TP95、异常数取消订单数等指标是否异常,可以提前发现提前发现潜在问题、提前解决;
  3. 全链路关键日志:通过记录全链路关键日志根据日志,自动分析反馈订单问题原因给絀处理结果,有效提高反馈处理效率

事中措施的目的是为及时发现问题、快速解决问题。

事中这块我们采取的手段包括:

  1. 订单监控大盤:实时监控订单业务指标,异常时报警;
  2. 系统监控大盘:实时监控订单系统指标异常时报警;
  3. 完善的SOP:报警后,通过标准流程快速萣位问题、解决问题。

事后措施是指问题发生后分析问题原因,彻底解决并将相关经验教训反哺给事前、事中措施,不断加强事先、倳中措施争取尽量提前发现问题,将问题扼杀在萌芽阶段

通过将之前人肉进行的运维操作自动化、智能化,提升了处理效率、减少了運维的人力投入

}

外卖店铺运营很多不是很懂互聯网的商家们,可能就直说单纯的在外卖平台中开一个店做一个简单的装修,放一个简单的活动然后就不去关注其他事了,就只等着接单就行了有订单就接一些,没有就靠线下门店的售卖对于互联网或者外卖比较熟的商家就好多了,会做很多的店铺优化不定时的會推出一些店铺的优惠活动。大部分商家觉得做好了这些就不用管其他的了但是大部分人都忽略了一个问题,那就是外卖的配送配送嘚方式对于店铺的营业额也是至关重要的。

外卖的配送分为六大方式你了解多少?

美团外卖下单流程专送的骑手都是属于美团外卖下单鋶程公司的内部员工是由美团外卖下单流程进行管理的,而且有规定的上下班时间其收费模式是由商家提成和顾客配送费组成,优点茬于比较正规且形象优质配送速度快。点是成本较高而且限制了配送时间和范围。值得注意的是开通了美团外卖下单流程专送的商家昰可以获得排名加权和专属标准的

美团外卖下单流程众包是美团外卖下单流程外卖的一个开发性的配送平台,通过众包的形式调动用户嘚盈余时间帮助商家进行配送。其收费模式一般是按照距离收费距离越远收费越高,优点在于成本较低收费范围广。缺点是配送速喥较慢单量不稳定。

美团外卖下单流程快递主要是用于预防美团外卖下单流程专送代理商发生特殊情况无法提供服务时作为备用的物鋶配送方式。收费模式也是商家提成加顾客的配送费优点在于和美团外卖下单流程专送相比,成本稍微低一点在针对消费者收费上,┅般比美团外卖下单流程专送低1至2元配送范围也更大。缺点是由于配送区域大所以配送速度会相对来说慢一些。

商家自配送顾名思义僦是自己安排店内服务人员或者组建专门的配送团队自行解决配送问题,这个适合于规模较大的品牌连锁商家优点是配送区域和时间限制小,更加自由灵活缺点是对于单量较低且用户分散的商家来说,会增加经营成本在遇到恶劣天气是,运力难以得到保障整体配送速度和服务水平偏低。

蜂鸟专送是由饿了么自行组建的外卖配送队伍对于配送速度和质量都提升了很高。另外蜂鸟专送还推出了“准时达”服务,除了一些特殊情况外用户在带有“准时达”标签的商家下单,如果餐品送达时间超过承诺时间10分钟系统将会为用户赔付一个无门槛红包,每个用户每天最多赔付三个红包

蜂鸟配送的收费模式除了平台向商家收取一定比例的佣金外,还会对消费者收取相應的配送费用优点在于时效快,覆盖广服务和形象都很好。缺点是对于商家来说经营成更高,而且有最低起送价的门槛配送时间囷区域都有一定的限制。

有市场就肯定有需求为了迎合市场需求,外卖市场中出现了很多主打同城物品配送业务的公司像达达、闪送、来啦跑腿等。

大体的配送方式就是这些当然还有很多都是属于跑腿公司的,这些配送的方式一般都是由公司内部的规定决定的将这些配送的方式都了解后,在经营外卖店铺上也会有很多的选择比如苦心思考如何提高店铺排名和曝光时,却不知道其实店铺申请美团外賣下单流程专送服务也会提升店铺的排名

}

美团外卖下单流程外卖从2013年9月成茭首单以来已走过了三个年头。时期事务飞速开展,美团外卖下单流程外卖由日均几单开展为日均500万单(9月11日已突破600万)的大型O2O互联網外卖服务渠道渠道支撑的品类也由开始外卖单品拓宽为全品类。

跟着订单量的增加、事务复杂度的提高外卖订单体系也在不断演化進化,从前期一个订单事务模块到现在分布式可扩展的高性能、高可用、高安稳订单体系全部开展过程中,订单体系阅历了几个显着的期间下面本篇文章将为我们介绍一下订单体系的演进过程,重点重视各期间的事务特征、应战及应对之道

为便利我们非常好地了解全蔀演进过程,我们首要看一下外卖事务

外卖订单业务对于及时性的要求很高,因此从技术角度来看实时性的优先级很高,从用户订餐開始算起直至送达,时效通常在一个小时左右如果超时,用户体验就会受到伤害成为一次糟糕的购物经历。

在一个小时之内订单會不断的变更状态,一直到最终送达这期间要求各阶段配合紧密,一定要保证订单有效且及时送达

下图是一个用户视角的订单流程图。

我们从一个普通用户的思维出发当他下达订单之后,会有一个什么流程

用户需要下单然后支付,这是整个订单发出的路径在这之後,商家接收订单完成制作,再之后我们的物流团队进行配送,送至终端用户然后就是确认收货、包括后续售后或完结订单等操作。

从技术上团队来看各个阶段其实是多个子服务共同配的结果:比如说用户在订单下达的阶段可能会有需要各个购物车、预览、接受订單服务共同匹配完成,这一系列的子服务又依赖于我们整体的底层基础服务来完成

另一个问题在于,外卖业务的时效性非常显著订单茬中午、傍晚时段会大批量的集中爆发,在其他时段数量则非常之少这导致,到某时间段之后整个系统的压力会急剧上升。

下图是一忝内的外卖订单量分布图

总结而言外卖业务具有如下特征:

  • 流程较长且实时性要求高;

下面将按时间脉络为大家讲解订单系统经历的各個阶段、各阶段业务特征、挑战以及应对之道。

在早期外卖业务起步阶段技术团队的第一目标是要能够急速验证我们整体业务的可行性,所以这阶段技术团队的主要任务就是保证我们的服务架构有足够的灵活性方便快速迭代,完成业务快速试错过程中的需求

因此,我們将订单相关功能组织成为模块化的服务将其与其他的模块一起拼装成jar包,这个包是公用的可以通过我们的各个系统来使用这个包,從而提供订单功能

早期系统的整体架构图如下所示:

在业务前期使用这种架构,整体来讲比较简单、灵活整个公共服务的逻辑通过集荿分配到各端,整个应用的开发部署相对比较简单十分适合我们前期的需求:前面已经提过,是逻辑简单、业务量不大方便与快速迭玳。

但是随着业务量持续上升,整个服务体系逻辑变得复杂业务量开始增加,因此我们现有架构的漏洞开始出现整个业务体系互相幹扰,出现了很多问题

我们考虑,在前期整个业务处在试探阶段初步的架构可以满足业务需求,也能够给提供快速迭代的支持但随著整个业务的成长、服务的成熟,我们应该对这个体系进行升级满足现阶段的需求。

在14年的4月左右外卖订单数量增长迅速,几乎达到烸天10万订单量的水平而且由于业务发展良好,这个数字每天都在不断攀升整体业务的大框架此时已经基本成型,集体业务在整体框架仩快速迭代

业务团队使用一个大项目进行开发部署,在此基础上互相影响业务沟通成本上升,大多数业务公用VM的情况也对业务整体產生了一定影响。

为解决开发、部署、运行时相互影响的问题我们将订单系统进行独立拆分,从而独立开发、部署、运行避免受其它業务影响。

系统拆分主要有如下几个原则:

  • 相关业务拆分独立系统;
  • 优先级一致的业务拆分独立系统;
  • 拆分系统包括业务服务和数据

出於以上考虑,我们把订单系统进行了整体的的独立拆分将接收到的所有订单服务通过接口提供给外部使用。

在内部订单系统中我们评估了功能优先级,按照优先级拆分成了不同的子系统以防止业务之间的相互影响,通过队列消息的形式订单系统可以通知外部订单状態的变更等情况。

独立拆分后的订单系统架构如下所示:

这其中最底层是数据存储层,负责订单相关数据的独立存储订单服务层,该層按照优先级划分为三个体系分别称之为交易体系、查询体系和异步处理的体系。

独立拆分后能够避免事务间的相互影响。迅速支持倳务迭代需要的一起保障体系稳定性。

高性能、高可用、高稳定的订单系统

在我们将订单系统进行拆分后业务之间的相互干扰大大降低,不仅保证了迭代的速度而且还很好的维持了系统的稳定性,在这期间整个业务的订单量开始逐渐想着百万大关迈进,并逐渐超出本来的小问题,在大量订单出现的时候覆盖面积加大对用户的试用体验相当不友好。举例说明再支付成功后,某些极端情况会导致支付成功的消息无法返回在终端显示没有支付。在巨量订单的前提下这种问题开始增加,我们必须进一步优化系统的可靠性保证我們的订单功能不会影响用户使用。

不仅如此订单量仍在不断增加的同时,一些业务逻辑相对复杂、混乱对于整个系统的使用提出了新嘚、更高的要求。

因此为了能够建设一个更加稳定并且可信赖的订单服务系统,我们必须再次对整个系统进行升级我们后文就会按照各个升级需求对整个升级过程进行描述。

系统独立拆分后可以方便地对订单系统进行优化升级。我们对独立拆分后的订单系统进行了很哆的性能优化工作提升服务整体性能,优化工作主要涉及如下几个方面

一个显而易见的道理是,同一时间需要处理的事情越少服务性能就会越高、速度越快,所以我们将通过将部分操作进行异步化处理减少整个操作进行的压力通过异步来提升服务气的性能。

以下使峩们提出的两种方案:

  • 线程或线程池:将异步操作放在单独线程中处理避免阻塞服务线程;
  • 消息异步:异步操作通过接收消息完成。

注意合理有一个隐患我们如何保障异步操作的执行?设想一下场景当应用重启时,如果是线程或者线程池的行的异步化在后台执行未唍成的情况下,jvm重启会造成相当大的影响

因此需要采取优雅关闭开保障业务的进行。当然如果采取消息异步,则无须考虑这个问题

具体到该系统,我们选择将某些没有必要同步进行的操作异步化从而提供更强的性能,例如我们发放红包或者推送消息等等全部采用了異步处理

以订单配送PUSH推送为例,将PUSH推送异步化后的处理流程变更如下所示:

PUSH异步化后线程#1在更新订单状态、发送消息后立即返回,而鈈用同步等待PUSH推送完成而PUSH推送异步在线程#2中完成。

操作并行化也是提升性能的一大利器并行化将原本串行的工作并行执行,降低整体處理时间我们对所有订单服务进行分析,将其中非相互依赖的操作并行化从而提升整体的响应时间。

以用户下单为例第一步是从各個依赖服务获取信息,包括门店、菜品、用户信息等获取这些信息并不需要相互依赖,故可以将其并行化并行后的处理流程变更如下所示:

通过将获取信息并行化,可有效缩短下单时间提升下单接口性能。

经过将核算信息进行提早核算后缓存防止获取数据时进行实時核算,然后提升获取核算数据的效劳功能比如关于首单、用户已减免配送费等,经过提早核算后缓存能够简化实时获取数据逻辑,節省时刻

以用户已减免配送费为例,假如需求实时核算则需求取到用户一切订单后,再进行核算这么实时核算成本较高。技术团队經过提早核算缓存用户已减免配送费。需求取用户已减免配送费时从缓存中取即可,不用实时核算具体来说,包含如下几点:

  • 通过緩存保存用户已减免配送费;
  • 用户下单时如果订单有减免配送费,增加缓存中用户减免配送费金额(异步进行);
  • 订单取消时如果订單有减免配送费,减少缓存中用户减免配送费金额(异步进行);

订单体系触及买卖需要确保数据的共同性。不然一旦出现疑问,可能会致使订单不能及时配送、买卖金额不对等

买卖一个很主要的特征是其操作具有业务性,订单体系是一个杂乱的分布式体系比方付絀触及订单体系、付出渠道、付出宝/网银等第三方。仅经过传统的数据库业务来确保不太可行关于订单买卖体系的业务性,并不请求严厲满意传统数据库业务的ACID性质只需要终究成果共同即可。对于订单体系的特征咱们经过如下种方法来确保终究成果的共同性。

经过延時重试确保操作终究会最执行。比方退款操作如退款时遇到网络或付出渠道毛病等疑问,会延时进行重试确保退款终究会被完结。偅试又会带来另一个疑问即有些操作重复进行,需要对操作进行幂等处理确保重试的正确性。

以退款操作为例参加重试/幂等后的处悝流程如下所示:

退款操作首先会查看是否现已退款,假如现已退款直接返回。不然向付出渠道建议退款,从而确保操作幂等防止偅复操作带来疑问。假如建议退款失利(比方网络或付出渠道毛病)会将使命放入延时行列,稍后重试不然,直接返回

经过重试+幂等,能够确保退款操作终究一定会完结

2PC是指分布式业务的两期间提交,经过2PC来确保多个体系的数据一致性比方下单过程中,触及库存、优惠资历等多个资本下单时会首先预占资本(对应2PC的第一期间),下单失利后会释放资本(对应2PC的回滚期间)成功后会运用资本(對应2PC的提交期间)。关于2PC网上有很多的说明,这儿不再持续打开

分布式体系的可用性由其各个组件的可用性一起决议,要提高分布式體系的可用性需求归纳提高构成分布式体系的各个组件的可用性。

对于订单体系而言其主要构成组件包括三类:存储层、中间件层、效劳层。下面将分层说明订单体系的可用性

存储层的组件如MySQL、ES等自身现已完成了高可用,比方MySQL经过主从集群、ES经过分片仿制来完成高可鼡存储层的高可用依靠各个存储组件即可。

分布式体系会大量用到各类中间件比方服务调用结构等,这类中间件通常使用开源商品或甴公司根底渠道供给自身已具有高可用。

在分布式体系中各个服务间经过彼此调用来完成事务功用,一旦某个服务出现问题会级联影响调用方的其他服务,进而致使体系溃散分布式体系中的依靠容灾是影响服务高可用的一个重要方面。

依靠容灾主要有如下几个思路:

订单系统会依赖多个其它服务也存在这个问题。当前订单系统通过同时采用上述四种方法来避免底层服务出现问题时,影响整体服務具体实现上,我们采用Hystrix框架来完成依赖容灾功能Hystrix框架采用上述四种方法,有效实现依赖容灾订单系统依赖容灾示意图如下所示

通過为每个依赖服务设置独立的线程池、合理的超时时间及出错时回退方法,有效避免服务出现问题时级联影响,导致整体服务不可用從而实现服务高可用。

另外订单系统服务层都是无状态服务,通过集群+多机房部署可以避免单点问题及机房故障,实现高可用

上面嘟是经过架构、技能完成层面来保证订单体系的功能、安稳性、可用性。实际中有很多的事端是人为因素致使的,除了好的架构、技能唍成外经过标准、准则来躲避人为事端也是保证功能、安稳性、可用性的重要方面。订单体系经过完善需要review、计划评定、代码review、测验上線、后续跟进流程来防止人为因素影响订单体系安稳性

经过以上办法,技术团队将订单体系建造成了一个高功能、高安稳、高可用的分咘式体系其中,交易体系tp99为150ms、查询体系tp99时刻为40ms全体体系可用性为6个9。

订单体系通过上面介绍的全体晋级后已经是一个高功能、高安穩、高可用的分布式体系。可是体系的的可拓展性还存在必定疑问部分效劳只能通过笔直拓展(添加效劳器装备)而不能通过水平拓展(加机器)来进行扩容。可是效劳器装备有上限,致使效劳全体容量受到约束

到2015年5月的时分,这个疑问就比较突出了其时,数据库效劳器写挨近单机上限事务预期还会持续快速增长。为确保事务的快速增长咱们对订单体系开始进行第2次晋级。方针是确保体系有满足的拓展性然后支持事务的快速开展。

分布式体系的拓展性依赖于分布式体系中各个组件的可拓展性关于订单体系而言,其首要组成組件包含三类:存储层、中间件层、效劳层下面将分层阐明怎么进步各层的可拓展性。

订单体系存储层首要依赖于MySQL耐久化、tair/redis cluster缓存tair/redis cluster缓存洎身即提供了极好的拓展性。MySQL能够通过添加从库来处理读拓展疑问可是,关于写MySQL存在单机容量的约束另外,数据库的全体容量受限于單机硬盘的约束

存储层的可拓展性改造首要是对MySQL拓展性改造。

写容量约束是受限于MySQL数据库单机处理才能约束假如能将数据拆为多份,鈈一样数据放在不一样机器上就能够便利对容量进行拓展。

对数据进行拆分通常分为两步第一步是分库,行将不一样表放不一样库不┅样机器上通过第一步分库后,容量得到必定提高可是,分库并不能处理单表容量超越单机约束的疑问跟着事务的开展,订单体系Φ的订单表即遇到了这个疑问

关于订单表超越单库容量的疑问,需求进行分表操作行将订单表数据进行拆分。单表数据拆分后处理叻写的疑问,可是假如查询数据不在同一个分片会带来查询功率的疑问(需求聚合多张表)。因为外卖在线事务对实时性、功能请求较高咱们关于每个首要的查询维度均保留一份数据(每份数据按查询维度进行分片),便利查询

具体来说,外卖首要涉及三个查询维度:订单ID、用户ID、门店ID对订单表分表时,关于一个订单咱们存三份,别离依照订单ID、用户ID、 门店ID以必定规矩存储在每个维度不一样分片Φ这么,能够涣散写压力一起,依照订单ID、用户ID、门店ID三个维度查询时数据均在一个分片,确保较高的查询功率

订单表分表后,訂单表的存储架构如下所示:

可以看到分表后,每个维度共有100张表分别放在4个库上面。对于同一个订单冗余存储了三份。未来随著业务发展,还可以继续通过将表分到不同机器上来持续获得容量的提升

分库分表后,订单数据存储到多个库多个表中为应用层查询帶来一定麻烦,解决分库分表后的查询主要有三种方案:

  • MySQL服务器端支持:目前不支持

由于MySQL服务器端不能支持,我们只剩下中间件和应用層两个方案中间件方案对应用透明,但是开发难度相对较大当时这块没有资源去支持。于是我们采用应用层方案来快速支持。结合應用开发框架(SPRING+MYBATIS)我们实现了一个轻量级的分库分表访问插件,避免将分库分表逻辑嵌入到业务代码分库分表插件的实现包括如下几個要点。

  • 配置文件管理分库分表配置信息;
  • JAVA注解说明SQL语句分库分表信息;
  • JAVA AOP解析注解+查询配置文件获取数据源及表名;
  • SPRING动态替换数据源。

通过分库分表解决了写容量扩展问题。但是分表后会给查询带来一定的限制,只能支持主要维度的查询其它维度的查询效率存在问題。

订单表分表之后对于ID、用户ID、门店ID外的查询(比如按照手机号前缀查询)存在效率问题。这部分通常是复杂查询可以通过全文搜索来支持。在订单系统中我们通过ES来解决分表后非分表维度的复杂查询效率问题。具体来说使用ES,主要涉及如下几点

  • 通过databus将订单数據同步到ES。
  • 同步数据时通过批量写入来降低ES写入压力。
  • 通过ES的分片机制来支持扩展性

通过对存储层的可扩展性改造,使得订单系统存儲层具有较好的可扩展性对于中间层的可扩展性与上面提到的中间层可用性一样,中间层本身已提供解决方案直接复用即可。对于服務层订单系统服务层提供的都是无状态服务,对于无状态服务通过增加机器,即可获得更高的容量完成扩容。

通过对订单系统各层鈳扩展性改造使得订单系统具备了较好的可扩展性,能够支持业务的持续发展当前,订单系统已具体千万单/日的容量

上面几部分都昰在介绍如何通过架构、技术实现等手段来搭建一个可靠、完善的订单系统。但是要保障系统的持续健康运行,光搭建系统还不够运維也是很重要的一环。

早期对系统及业务的运维主要是采用人肉的方式,即外部反馈问题RD通过排查日志等来定位问题。随着系统的复雜、业务的增长问题排查难度不断加大,同时反馈问题的数量也在逐步增多通过人肉方式效率偏低,并不能很好的满足业务的需求

為提升运维效率、降低人力成本,我们对系统及业务运维进行自动化、智能化改进改进包括事前、事中、事后措施。

事前措施的目的是為提前发现隐患提前解决,避免问题恶化

在事前措施这块,我们主要采取如下几个手段:

  1. 定期线上压测:通过线上压测准确评估系統容量,提前发现系统隐患;
  2. 周期性系统健康体检:通过周期检测CPU利用率、内存利用率、接口QPS、接口TP95、异常数取消订单数等指标是否异瑺,可以提前发现提前发现潜在问题、提前解决;
  3. 全链路关键日志:通过记录全链路关键日志根据日志,自动分析反馈订单问题原因給出处理结果,有效提高反馈处理效率

事中措施的目的是为及时发现问题、快速解决问题。

事中这块我们采取的手段包括:

  1. 订单监控夶盘:实时监控订单业务指标,异常时报警;
  2. 系统监控大盘:实时监控订单系统指标异常时报警;
  3. 完善的SOP:报警后,通过标准流程快速定位问题、解决问题。

事后措施是指问题发生后分析问题原因,彻底解决并将相关经验教训反哺给事前、事中措施,不断加强事先、事中措施争取尽量提前发现问题,将问题扼杀在萌芽阶段

通过将之前人肉进行的运维操作自动化、智能化,提升了处理效率、减少叻运维的人力投入

}

我要回帖

更多关于 美团外卖下单流程 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信