写点什么

计价系统在滴滴的应用与实践

  • 2021-05-10
  • 本文字数:5910 字

    阅读完需:约 19 分钟

计价系统在滴滴的应用与实践

计价系统的价值


滴滴的出行交易形态大致可分为预估、发单、抢单成功、司机到达、开始计费、实时计费、结束计费、发起收款、支付等环节。价格作为其中的核心属性,贯穿着整个订单流程,而计价要解决的就是和价格相关的问题。 

 


对用户的价值


对于出行场景而言,价格是影响用户决策的最重要因素之一,计价给用户提供的核心价值就是准确的价格计算。 


出行服务和普通商品在价格上最大的不同就在于二者定价方式的不同,用户在电商平台买一件衣服或者在线下实体店买一件商品亦或是去餐厅吃一次午餐,用户应付的都是相对固定的价格,虽然价格会有波动但标准商品的定价方式决定了其在一段时间中是固定不变的,但出行服务不一样,不管是传统的出租车还是如今的网约车,每次乘客出行都可以说是一次定制化的服务过程,起终点的不同、行车路线的拥堵情况、行车的时长、等等因素都可能影响最后的出行费用。 


对于用户而言,计价系统最重要的任务就是把价格算明白。目前在发单时,用户输入起终点后,平台根据实时路况、预估行驶时长等因素综合估算出来了一个预估价,供乘客作为出行参考。预估价不同等于实时价格,其主要目的是方便用户做决定。在这一环节,计价系统都竭力保障用户看到的是一个能反映此次行程所有影响因素的准确价格。此外,在行程中的实时计费和行程结束后的账单明细,计价系统都在用户提供高效、稳定、准确的价格计算服务。


对业务的价值


供需关系也会影响网约车的价格。面对季节性的供需变化,平台网约车也已经开始尝试淡旺季调价,在出行旺季适度涨价,鼓励司机多出车接单,帮助乘客更快叫到车,同时提升司机收入;在出行淡季适度降价,通过优惠吸引更多乘客打车,保障司机接单量从而稳定收入减少波动,让用户和司机达成有效的撮合。在这个过程中,计价系统为业务方提供了各种价格相关的能力,包括但不限于定价(城市、围栏、场景)、开放计价、价格权益等能力,从价格定义、定价调整、价格活动运营、价格计算、价格感知到最后价格的异议复盘等提供一站式价格服务。 


除了提供这些具体的能力之外,计价作为滴滴平台的中台服务,承载了网约车、 国际化、单车、共享汽车、包车、国际化顺风车等多业务线、多产品形态的价格服务,通过中台能力复用,为公司的降本增效添一份力。


计价系统的技术架构


宏观上看,整个计价系统是由多个子模块组成的分布式系统,对外提供 HTTP 接口接入,并提供封装好的 SDK 方便业务方高效对接,内部模块通信则使用更高效的 thrift 协议进行通信,与此同时计价还依赖滴滴平台提供的各类服务如地图、围栏、订单等等,数据层则使用 codis、ddmq(自研消息队列已开源)、fusion(自研 NewSQL)、MySQL、ES、HDFS 等组件。整个系统架构如下图所示:


 

从上往下来看,各模块提供的功能如下:

 

InRouter 网关是滴滴平台的统一网关入口,通用的网关功能无需多言,对于计价而言比较特殊的是其提供了基于司机 id 的一致性 hash,一致性 hash 会将同一司机的请求打到同一台机器,在整个系统内部,我们对大量数据做了内存级的缓存,用于提效和降级兜底。


Application 层是计价的基础计价模块,承担计价主流程,负责对外提供服务,包括预估价格计算、配置搜索查找、行程轨迹计算、费用聚合等核心能力。该模块是整个在线系统的主要出入口,模块本身无状态可以进行无限水平扩展,在高峰期可以通过滴滴云平台完成分钟级别的扩容。

       

config 模块是一个高度灵活抽象的配置平台。其配置包含多种多样,包括城市、围栏、场景、开放化计价等定价功能模块,同时还包含价格权益、i18n 多国语言、费用项定义等模块,配置平台将不同的业务配置抽象成一个个模块,一个模块对应一个配置列表,每个配置都包含的所见即所得的编辑组件,如下拉框、文本框、日期选择等组件,这些组件可以进行自助化定制、编排、组合以满足不同配置要求。同时通过 RBAC 权限校验机制进行权限隔离,确保了敏感数据的权限收敛。通过灵活抽象,做到了与业务完全解耦,成为一个通用化的配置平台。其底层则使用滴滴平台及的配置服务 Apollo 来连接线上环境,从运营更改配置到线上生效可以做到分钟级的速度。Apollo 是一个适用于多种场景的 A/B 实验与灰度发布、配置同步的平台,通过科学合理的 AB 实验数据辅助业务决策与效果分析,利用简单易用的灰度、配置功能提升开发效率,降低上线风险。 


module 层是滴滴内部的基础组件,包含服务发现、分布式配置中心,metric&trace&log、rpc 通信框架等基础服务组件。


service layer 服务层是包含十余种服务的依赖层,计价将一些比较独立的功能拆分成单独的子模块,一方面在功能和业务上进行解耦以降低基础计价的复杂度,一方面提高系统稳定性和迭代效率。下面介绍其中一些服务模块:


ETA 是地图平台提供的路径规划服务,为计价提供预估计算时的路线规划能力;Cratos 是开放化计价服务,通过热插拔的插件、接口回调等机制,为业务方提供干预账单的能力。Dealer 则是账单渲染模块,承担账单明细、计价规则等费用感知的页面渲染。Fence 服务是滴滴内部的地理围栏服务,通过查询 Fence 服务,可以知道一个坐标点是否在一个特定的电子围栏中。


接下来介绍下数据层。


整个在线系统底层的存储依赖为 Codis 和 fusion;Codis 是一个分布式 Redis 解决方案。Fusion 则是滴滴自研的分布式 NewSQL 数据库,完全支持 Redis 协议,部分支持 MySQL 协议,并提供 PB 级别持久化、跨机房多活、FastLoad 导数据、单机跨行事务、binlog 吐出等高级功能。系统主要依赖 Codis 进行在线热数据的操作,如行程中的订单信息,其中包含像当前位置经纬度,累积走过的时长、里程等关键信息,这些信息会在每一次坐标点上报之后进行更新,计算出当前实时账单发送给司乘两侧以感知当前的实时费用情况。Codis 的部署为双机房双主互相同步,通过前面介绍的一致性 hash 机制,可以确保同一个司机的请求只会在一个机房,同时因为双机房实时互相同步,因此一旦某个机房出现问题,另一个机房都包含系统的全部数据,出现这类故障之后,线上故障检测系统会第一时间报警,经过确认后将流量切到没有问题的机房,从而确保整个系统的稳定。


系统使用 Fusion 进行持久化的数据存储,这部分数据相比 Codis 而言存储时间更长、容量更大,数据除了用于进行离线分析之外,我们用其作为 Codis 的兜底,保障系统数据层的健壮性。


除了上面提到的两个数据库之外我们还使用 ElasticSearch&Kibana 进行线上日志的存储 &检索;使用 HDFS 进行数据的长期归档保存,确保可进行长时间段的追溯;使用 DDMQ 进行业务数据的传递。


计价系统的挑战


在整个计价系统演进过程中,系统从比较简单的计价器到如今复杂的价格系统,一路上面对非常多的挑战,下面从系统稳定性、计价准确性、迭代高效性三个方面进行介绍。 


4.1 稳定性


计价系统作为业务主流程中的一环,稳定性是衡量计价系统的重要因素。在滴滴内部,我们用两个指标衡量稳定性,首先是不可用时长,第二是不同等级的事故数量。在稳定性方面我们做了大量的工作,本文从两个维度介绍:人、架构:


先说说人。系统的故障来源大致可分为两类,人为因素和自然因素。自然因素,常见的如网络波动、机器故障等,不常见的如断电、地震、火灾等,这些我们很难提前避免,只能做好预案建设;人为因素则是我们可以通过一些机制避免的,最常见的如逻辑 bug、系统设计问题等。为了降低人为因素导致的故障,我们从以下几个方面建立健全机制:


  • 第一,严格的上线流程。首先是代码 review 制度,所有的上线代码都必须经过至少一人的 review,一些重大更新需要经过两人甚至多人的反复 review,以降低各类逻辑错误,同时在系统设计层面需要经过更有经验的工程师的 review 才能上线。那我们是如何保证这个制度有效执行的呢?首先是流程层面,整个上线发布流程都是在滴滴内部的统一发布平台进行,在上面每一步操作都会留痕,同时该系统保证了只有经过 review 的代码才能合入 master 分支,其次是责任方面,如果因为某一次上线导致出故障,那么故障的责任由代码作者和 review 人共同承担。其次是上线操作的规范化,在滴滴内部,我们总结了五条线上变更军规:提前通报要记得、变更步骤要完备、分级发布要遵守、高峰窗口要避免、服务检查要执行,每一步都通过上线发布系统确保发布人严格执行流程。

  • 第二,反馈与响应机制的建设。计价虽然模块众多,但每个模块都有唯一的接口人负责其稳定性,各模块的接口人需要确保在模块有问题时,第一时间响应。同时我们还有 oncall 制度,每周都有轮值的值班人员,对整个计价系统的稳定性进行第一时间响应。

  • 第三,每周的全员稳定性复盘。通常由本周 oncall 的同学向全体组员汇报本周系统的稳定性情况,分享本周系统稳定性相关情况,提高全员的稳定性意识,对于 oncall 期间发现的问题,需要制定解决方案及时间排期,做到问题的早发现,早排查,早解决。


接下来说一下架构层面。这里介绍两点,非核心功能解耦及防御性编程。 


非核心功能解耦指的是不在核心流程中的功能我们都尽量将其隔离出来,避免影响到主流程,如工具类、查询类等旁支功能,在计价系统中的判定标准就是在一次实际打车过程中如果没有这个功能是否可以继续进行,为此我们解耦出了多个模块,如配置平台、dealer 渲染模块、cratos 开放化计价模块等等。解耦带来的好处多种多样,首先就是故障异常的解耦,解耦出来的模块其稳定性、性能甚至是逻辑问题都不会干扰核心流程,其次是当真正的故障来临时,这些非核心功能都可以做到一键降级,比如 dealer 渲染模块,经过降级之后就没有费用明细页,但总价依旧保留,通过这种有损的降级,我们保障了打车的核心体验依旧是完备的。


防御性编程是一种系统设计思想,它是为了保证对程序的不可预见的使用不会造成程序功能上的损坏。具体在日常系统设计上有两部分,首先对所有外部依赖保持高度不信任,所有第三方依赖都需要有降级兜底方案,尤其是涉及核心功能的依赖,如数据库。在计价中,我们对大量的核心依赖都有降级兜底方案,如最重要的核心存储 Codis 我们有三层降级兜底,从内存、fusion 再到上游透传数据,确保打车过程中即使 Codis 全挂,虽然可能有损但不影响核心流程的继续。其次是在日常的编码过程中,需要确保每个函数的健壮性,对于入参,不能做预设应及时返回错误。『凡是可能出错的地方就一定会出错』,墨菲定律告诉我们不应该心存侥幸,对于日常的编码工作,要将稳定性时常放在心上。


4.2 准确性


在价格计算的准确性上以时间和里程的精准计算为例。


在计算时间时,所有时间都经过服务端的校准,避免人为因素导致时间误差。除此之外在行程中的时间计算是通过每秒一个坐标点的上报,可以将时间的计算精度控制在秒级,而我们的计费规则只会精确到分钟级别;对于上报上来的坐标点,我们也并非全盘接受,首先相邻坐标点经过严格校验,必须符合准入规则才予以采纳,对于异常的点,系统会进行记录和报警以及时发现异常。


在里程计算方面,首先两坐标点之间的距离计算并不是用直线距离计算而是使用球面距离,如下图公式所示:




其次手机 GPS 定位可能出现漂移,系统会将每个上报过来的点进行绑路处理,确保坐标点落在车道而非路的两侧,和时间一样,对于前后差异过大的两个坐标点,系统同样会判定无效,避免因为手机、系统或者人为因素导致距离计算的不精确。


4.3 高效性


作为与价格最密切相关的系统,业务方提出的需求是又多又快又复杂,计价团队为了快速响应业务方的迭代需求,提升中台复用价值,通过配置化、自助化支持了大量业务需求,下面从开放化计价和价格权益两方面介绍。


  • 开放化计价:开放化计价干预是独立于基础计价之外的计价引擎,与基础计价不同的是,该系统负责计算非基础计价的费用项,以及需要请求第三方的费用项。比如:企业级保险费、跨城费、补贴、多因素费用项等。其设计目标是将业务的计价干预需求与计价引擎相分离,建设计价系统中台。 

  • 在一个订单主流程事件有:预估、发单、抢单成功、司机到达、开始计费、实时计费、结束计费、发起收款、支付等环节等多个事件。我们将这些事件抽象成完整的上下文,在每个事件发生时都回调给业务方的接口或插件中。通过统一规范的输入输出,将期望干预账单的依赖反转,所有期望对账单干预的业务方都可以接入这套开放化计价体系,不同的业务方之间的隔离则由计价内部进行,通过这套体系计价团队释放出的人力资源又着力于建设账单工具、行程回放等功能帮助团队进一步提效。   

  • 截止到目前,我们已经通过这套系统接入了近百余项费用,如果这些都由账单系统来定制开发,那我们势必会成为迭代的瓶颈。

  • 价格权益:在出行系统中决定最后总价格的依赖因素非常多,如是否拼车、是否是会员、是否有优惠券等等多个变量,所以出行系统中的优惠计算会变得越来越精细化,同样优惠手段也会越来越多,如:总价折扣、费用组合折扣、单项费用折扣、一口价、时长减免、里程减免等等。 

  • 如果每次都定制开发,不管是人力还是时间上,计价团队都很难跟上业务快速迭代的步伐。为了应对如此复杂变化的价格运营需求,计价系统抽象出『价格权益』模块,以应对复杂的价格运营需求。 

  • 价格权益有两大法宝,法宝一:多维度特征识别,如产品线、车型、场景、人群、区域、围栏、路线等等,同时对新增维度保持高度可扩展性,基于这些识别出来的维度,价格权益做第二件事即对价格进行干预,此处会用到法宝二:多维度立体的价格干预手段,如新增费用项、对单个费用项进行加减 &系数计算 &免除、一口价、免单、里程 &时长干预等等。同时在感知侧优化升级,凸显出用户所享受的会员权益价格属性,给用户带来更好的出行体验。所有的价格运营活动全部可以通过配置化的方式实现分钟级上线,大大提高价格运营的效率。 

  • 在 2020 年全年价格权益在规则判定、价格运营场景、感知能力与模板化、工具等 9 大类 23 小类功能进行了高节奏迭代。在业务开展上,通过能力复用支持了多条业务线、多种价格权益、千万级订单量的权益核销,为业务带来了全新的价格运营体验与思路,在拉新、促活、补贴,定价评估等多增长方向提供了有效的价格调控解决方案。在需求支持和研发侧做到了降本提效。在 C 端补贴、公益免单、身份专属等多个价格方向初步落地了一些具有长期业务价值的需求,例如孕妈专属优惠、疫情期间医护车队免费接送医护人员等,以及青桔单车早高峰免单活动等。



目前开放化定价与价格权益已经形成完整的精细化定价体系,成为价格这一重要领域的支柱体系。 


当然,我们的产品和系统还有很多不完善的地方,欢迎大家提出宝贵的意见,帮助我们更好的成长,谢谢。



头图:Unsplash

作者:滴滴智能中台

原文:https://mp.weixin.qq.com/s/hV0_pDRBisr_vOwKpqjdYQ

原文:计价系统在滴滴的应用与实践

来源:滴滴技术 - 微信公众号 [ID:didi_tech]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2021-05-10 00:003668

评论

发布
暂无评论
发现更多内容

面试官问:僵尸进程和孤儿进程有了解过吗

Java小咖秀

Linux 学习 面试 进程 经验

揭秘淘宝平台广告策略,拆解最佳投放实践

华为云开发者联盟

数据分析 广告 用户增长 淘宝 电商

轻量级BI应用-Superset实践

Jackchang234987

BI 数据产品

百万并发「零拷贝」技术系列之经典案例Netty

码农神说

Java Netty 零拷贝

判了!中科大博士写游戏外挂赚了12万获刑,被抓才知道帮团队赚了300万……

程序员生活志

游戏开发 游戏 游戏外挂 新闻

信创舆情一线--50多家科技公司源代码泄露

统小信uos

知识点梳理:聊聊iOS SDK数据采集那点事儿

易观大数据

第8周回顾

慵秋

架构师训练营第8周学习总结

TH

一图看懂华为云DevCloud如何应对敏捷开发的测试挑战

华为云开发者联盟

微服务 敏捷开发 测试 云服务 华为云

使用Spring Validation优雅地校验参数

Java课代表

springboot

该学一学了!零基础入门Docker

程序员的时光

Docker

MySQL的索引基础知识

guoguo 👻

要都练基本功

架构师

架构师训练营week08 作业

GunShotPanda

【解构系统设计面试】什么是系统设计?以及如何设计一个新鲜事系统?

罗远航

系统设计

第八周总结

LEAF

Java中的模板设计模式,太实用了!

BUZHIDAO

Java

一次线上JVM Young GC调优,搞懂了这么多东西!

南方有乔木兮

求组队,PK华为HMS全球应用创新大赛!

InfoQ_e92167c73263

android

视频丨包不同的沙雕敏捷之砸锅卖铁买兰博

华为云开发者联盟

程序员 运维 敏捷 敏捷开发 技术人

第八周总结

Acker飏

2行代码搞定一个定时器!

简爱W

单向链表合并算法

走过路过飞过

架构师培训 -08总结 数据结构算法,网络通信协议,非阻塞网络 I/O,数据库原理

刘敏

判断两个链表是否合并

Acker飏

Developer 转型记:一个开发平台的“魔力”

华为云开发者联盟

华为 AI 开发者 开发者工具 华为云

Java SSM 框架常见面试题

老大哥

Java

架构师训练营week08 学习总结

GunShotPanda

JVM详解之:HotSpot VM中的Intrinsic methods

程序那些事

Java JVM GC

BFC "苦"前端久矣!

catcoolion

CSS 大前端

计价系统在滴滴的应用与实践_语言 & 开发_滴滴技术_InfoQ精选文章