文章作者:李金康 美团 高级技术专家

内容来源:Frank

出品平台:DataFunTalk

导读: 2019年5月,美团正式推出新品牌「美团配送」,升级配送开放平台。那你知道支撑美团配送大脑的实时特征平台是如何建设的吗?如何实现每分钟生产千万级的实时特征?如何在70w+QPS的场景下实现4个9响应耗时在50毫秒的需求?本文将为大家介绍配送实时特征平台的发展历程,关键技术和实践经验。

01 配送业务介绍

1. 商业模型

配送的业务最主要的就是一个履约的行为,将用户、商家和骑手关联起来,促进配送效率提升、用户体验提高、配送成本降低,从而形成一个闭环的商业模型。

即时配送平台核心职责就是调整好用户、商家、骑手三元的关系,用更低的成本为用户带来更好的体验,为商家带来更多的单量,为骑手带来更多的收入。

2. 履约模型

配送就是一个履约的过程,不像电商主要是线上完成,配送主要是线下完成履约。

  • 物理世界中,一个运单的完成过程是从用户下单开始到用户收餐骑手离客为止,需经历一系列室内室外的场景——用户下单,系统派单,骑手室外骑行到目的地然后下车步行到商家,等待取餐驻留室内,商家出餐,骑手取餐离店后步行上车,室外骑行到用户目的地,下车步行上楼送餐,驻留室内等待用户收餐,最后用户收餐骑手离客。
  • 可以看到物理世界是比较复杂的一个过程,那就需要智能决策系统来做一定的调度,派给哪个骑手?何时到店取餐?同时要做一个合理的定价,针对恶劣天气和爬楼梯等特殊情况收的费用肯定是不同的,收多少配送费?付给骑手多少配送费?最后还要给出一个合理的时间预估,配送时长是多少?商家多久可以出餐?
  • 算法要做以上这些智能决策过程中,就需要做履约过程整个链路的数字化,通过实时特征平台来做实时感知的数字化,通过AIoT平台完成如骑手骑行、爬楼等行为精准感知的数字化;本次主要介绍实时感知数字化的实时特征平台。

02 实时特征平台建设

1. 背景

2017年开始做实时特征平台建设的背景是为了解决两大问题:

  • 千万订单履约过程智能化:最开始履约过程是由简单的规则构建的,现在要实现从规则配置化向智能化过渡,包含智能调度、ETA时间预估、配送费定价和爆单等场景;算法实时决策需要分钟级数据的时效性。
  • 现有开发模式无法及时响应:当时实时特征开发散落在4个业务团队,进行烟囱式开发,流程长、效率低,存在一些重复建设;实时特征开发耦合在业务系统中,稳定性风险较高。

2. 目标&规划

基于建设背景,设定了建设目标——建设分钟级时效的实时特征平台,多粒度刻画履约过程,提升研发效率,降低研发成本。

基于建设目标,设定了三阶段的演进计划:

  • 第一阶段——系统化:和业务系统划清边界、确定实时平台架构;将系统搭建起来,验证是否可以支撑业务场景;将新增特征进行收口管理。
  • 第二阶段——规模化:建设高可用的系统,支撑更多的实时特征,将旧特征“绞杀”进行统一收口管理。
  • 第三阶段——平台化:将实时计算整合,进行完善的服务治理。

3. 系统化

① 设计思路

② 整体架构

进行系统化整体架构设计时,先制定了左侧的架构标准:

  • 流程标准化:从数据输入,加工计算到数据输出做了一个流程的标准化。
  • 数据分层,将共性沉淀下来。
  • 特征兜底,降低风险。

基于架构标准,最终制定了右侧的架构图,共分为6层:

  • 数据源层:主要有包裹表、运单表、骑手表以及运单扩展表。
  • 数据层:ODS层将数据进行清洗和转换,在DWD进行维表建模和合流,最后形成索引数据和明细数据的宽表。
  • 计算层:通过标准化的SQL对宽表数据进行计算。
  • 存储层:存储计算层输出的特征数据。
  • 服务层:通过实时特征服务将存储层数据统一输出应用层应用。
  • 应用层:主要有ETA时间预估策略服务、调度策略服务、保单策略服务以及定价策略服务。
  • 管理系统:主要就是一些元数据的管理,比如数据源、特征口径以及存储的管理;还包含兜底策略管理,降级模块,可以对单特征降级,也支持批量降级的核按钮。

③ 数据层关键点

做实时数据系统大都会碰到两个挑战:

  • 流乱序问题
  • 端到端的Exactly-Once语义保障

针对以上挑战,结合配送的实际业务场景给出对应的解决思路:

  • 提前构建“拼图”模板,实时填充:结合物理世界的配送履约过程,构建业务宽表,涵盖下单时间、支付时间、发单时间、调度时间、接单时间、取餐时间、送达时间等,根据实时数据流填充模板宽表,避免各数据流填各自的字段,避免乱序问题。
  • 上游合流保证不丢,下游解决重复问题。

④ 计算层关键点

2017年调研了一些行业解决方案:

  • Storm开发运维成本较高、SQL化难度高。
  • Flink没有现在这么火,稳定性无法保障;Spark Streaming不是公司运维的关键点,对于线上场景的稳定性也是无法保障。
  • 耦合在业务系统内部的基于Rpc计算在公司有成熟的监控运维体系和技术框架,但有一个问题是,该场景主要是基于关系型数据库进行计算的,例如MySQL,是存在单点问题的,扩展较难。

因为对基于Rpc的计算是相对有把握的,所以首先升级计算框架,将原有基于关系数据库计算升级为基于内存计算,计算是无状态、可扩展的;为了防止数据倾斜,基于业务特点进行提前按区域分片,采用“能者多劳”模式,计算比较快的节点就多计算一些。

接下来介绍下计算层的核心逻辑:

  • 首先,数据层形成的宽表,主要存储在外存中,例如运单包裹合流信息,那它如何和区域dim起来?就是通过索引表,将区域和运单关联起来。
  • 其次,全国有多少区域是确定的,每隔一分钟会通过定时任务将全国的区域放到MQ中。
  • 最后,就是实时特征计算服务FCS,每个计算节点有多个worker,每个worker中有task会做基于内存数据库H2的计算,当收到MQ的区域信息后,会拉取对应区域的宽表数据,在H2中计算实时特征,计算完成后会继续计算下一批的实时特征。

⑤ 阶段成果

建设系统化的阶段成果主要有:

  • 刻画粒度:维度上主要有商家和区域;粒度上主要有订单、运单、包裹。
  • 效率:特征上线由原来的多天提升到分钟级,收口新特征有60多个。
  • 接入量:接入9个算法模型、15个算法版本。
  • 稳定性:通过特征兜底策略避免了Kafka集群故障,系统没有S级事故。

4. 规模化

① 数据服务挑战&思路

第二阶段规模化建设的背景就是推动实时特征收口。

在外卖的图中会显示每单的配送时长,看上去这是一个指标,但实际上这个指标从外卖到配送经过的链路是很长的,最少有五六个节点,虽然只是一个ETA的预估时间,但是涉及到的特征可能有60个左右;另外,商家列表页会几百个商家,还要做排序,这样对实时特征的压力非常大,对实时特征的查询性能有更高的要求,通常200毫秒的延迟用户就会感知到。所以实时特征计算就会面临两个问题:

  • 稳定性要求高:交易链路
  • 性能要求高:50ms响应时间

解决以上问题的主要思路有:

  • 定制度:“135”制度,1分钟响应问题,3分钟定位问题,5分钟恢复计算
  • 保稳定:做全链路的监控和降级
  • 提性能:满足50ms的响应时间

② 稳定性建设框架

结合实际问题,制定了稳定性建设的框架:

  • 四层监控体系:硬件监控(CPU/网络/磁盘/内存)、基础组件监控(DB/MQ/ES/缓存)、服务监控(性能/异常/超时率/QPS)以及全链路数据质量监控。
  • 容灾体系:事前会做隔离、双缓存的架构设计,1.5倍容量规划以及定期压测;事中会做熔断、限流,三层降级(计算、服务、算法各层都有各自的降级兜底策略)的容错降级机制;事后主要是做CaseStudy的总结以及报警工具的完善,同时还要对实时索引和离线数据进行修复。
  • 制度:有完善的技术方案review机制、代码reiview机制、上线制度、巡检制度、值班制度以及报警治理等制度,最终形成一套可监控、可灰度、可回滚的技术体系。

③ 稳定性建设:拆分、隔离

在规模化稳定性建设的拆分和隔离上,主要做法如下:

  • 服务链路:遵循按照业务场景垂直拆分、一套代码部署隔离的服务/存储拆分原则,将实时特征服务拆分为ETA、调度、定价、爆单四个服务,在物理环境上进行隔离,但是使用的是同一套代码。
  • 计算链路:通过双机房(rz、gh)热备、三种场景集群(监控、运营、履约)对Storm集群进行拆分;使用美团自研的多机房Mafka集群做了MQ容灾,替换了单机房Kafka集群;对于数据收集的canal做了隔离,离线、实时、zk隔离,并做了多机房的容灾。

④ 数据质量

在数据质量上做了全链路过程质量的监控:

  • 流计算:监控时效性;
  • FCS实时特征计算:监控性能、延迟、完备性、准确性;
  • FFS实时特征服务:监控响应时间、可用性、容量;
  • 特征结果:监控准确性、完备性。

例如:数据清洗中会关注消息处理耗时;FCS服务会关注event流入总量、sql流入总量、内存表记录数、空值特征比例、单批次计算耗时;宽表会关注宽表记录数、未填充字段占比、不合理记录占比;特征质量会关注骑手平均负载最大值发生的时间、区域特征个数95分位数、商家平均特征个数、骑手负载中位数、众数等;FFS服务会关注每次请求耗时、请求密度、请求成功率和QPS等。

⑤ 查询服务性能优化

做查询服务性能优化主要有三个思路:

  • IO:使用批量、分组方式降低IO频次;使用PB格式替换原JSON格式、去除无用字段等减负瘦身方式来降低IO大小;使用高速的本地缓存。
  • CPU:减少Stop The World时间,使用G1替换了原来的CMS。
  • 内存:减少对象创建,控制对象大小�