资源预览内容
第1页 / 共14页
第2页 / 共14页
第3页 / 共14页
第4页 / 共14页
第5页 / 共14页
第6页 / 共14页
第7页 / 共14页
第8页 / 共14页
第9页 / 共14页
第10页 / 共14页
亲,该文档总共14页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
计价系统并发架构如何设计?导读:计价是出行业务中非常重要的一部分。在滴滴,不同的业务有不同的计价方式,比如网约车不仅有根据里程、时长、时段等进行的分时计价,在拼车、特惠快车等场景还支持一口价,青桔则主要基于起步价和时长费等来计价,而出租车则依赖于计价器计价,司机可线上手动输入车费由乘客支付等。经过多年的探索,我们演化出一套功能强大的计价系统,围绕价格计算这一核心属性提供了丰富强大的功能。目前计价系统服务于滴滴各条业务线,为各个出行场景下价格相关的问题提供解决方案。接下来从计价系统的价值、架构及挑战三个维度展开介绍。1.计价系统的价值滴滴的出行交易形态大致可分为预估、发单、抢单成功、司机到达、开始计费、实时计费、结束计费、发起收款、支付等环节。价格作为其中的核心属性,贯穿着整个订单流程,而计价要解决的就是和价格相关的问题。1.对用户的价值对于出行场景而言,价格是影响用户决策的最重要因素之一,计价给用户提供的核心价值就是准确的价格计算。出行服务和普通商品在价格上最大的不同就在于二者定价方式的不同,用户在电商平台买一件衣服或者在线下实体店买一件商品亦或是去餐厅吃一次午餐,用户应付的都是相对固定的价格,虽然价格会有波动但标准商品的定价方式决定了其在一段时间中是固定不变的,但出行服务不一样,不管是传统的出租车还是如今的网约车,每次乘客出行都可以说是一次定制化的服务过程,起终点的不同、行车路线的拥堵情况、行车的时长、等等因素都可能影响最后的出行费用。对于用户而言,计价系统最重要的任务就是把价格算明白。目前在发单时,用户输入起终点后,平台根据实时路况、预估行驶时长等因素综合估算出来了一个预估价,供乘客作为出行参考。预估价不同等于实时价格,其主要目的是方便用户做决定。在这一环节,计价系统都竭力保障用户看到的是一个能反映此次行程所有影响因素的准确价格。此外,在行程中的实时计费和行程结束后的账单明细,计价系统都在用户提供高效、稳定、准确的价格计算服务。2.对业务的价值供需关系也会影响网约车的价格。面对季节性的供需变化,平台网约车也已经开始尝试淡旺季调价,在出行旺季适度涨价,鼓励司机多出车接单,帮助乘客更快叫到车,同时提升司机收入;在出行淡季适度降价,通过优惠吸引更多乘客打车,保障司机接单量从而稳定收入减少波动,让用户和司机达成有效的撮合。在这个过程中,计价系统为业务方提供了各种价格相关的能力,包括但不限于定价(城市、围栏、场景)、开放计价、价格权益等能力,从价格定义、定价调整、价格活动运营、价格计算、价格感知到最后价格的异议复盘等提供一站式价格服务。除了提供这些具体的能力之外,计价作为滴滴平台的中台服务,承载了网约车、 国际化、单车、共享汽车、包车、国际化顺风车等多业务线、多产品形态的价格服务,通过中台能力复用,为公司的降本增效添一份力。3.计价系统的技术架构宏观上看,整个计价系统是由多个子模块组成的分布式系统,对外提供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.计价系统的挑战在整个计价系统演进过程中,系统从比较简单的计价器到如今复杂的价格系统,一路上面对非常多的挑战,下面从系统稳定性、计价准确性、迭代高效性三个方面进行介绍。4.1 稳定性计价系统作为业务主流程中的一环,稳定性是衡量计价系统的重要因素。在滴滴内部,我们用两个指标衡量稳定性,首先是不可用时长,第二是不同等级的事故数量。在稳定性方面我们做了大量的工作,本文从两个维度介绍:人、架构:先说说人。系统的故障来源大致可分为两类,人为因素和自然因素。自然因素,常见的如网络波动、机器故障等,不常见的如断电、地震、火灾等,这些我们很难提前避免,只能做好预案建设;人为因素则是我们可以通过一些机制避免的,最常见的如逻辑bug、系统设计问题等。为了降低人为因素导致的故障,我们从以下几个方面建立健全机制: 第一,严格的上线流程。首先是代码review制度,所有的上线代码都必须经过至少一人的review,一些重大更新需要经过两人甚至多人的反复review,以降低各类逻辑错误,同时在系统设计层面需要经过更有经验的工程师的review才能上线。那我们是如何保证这个制度有效执行的呢?首先是流程层面,整个上线发布流程都是在滴滴内部的统一发布平台进行,在上面每一步操作都会留痕,同时该系统保证了只有经过review的代码才能合入master分支,其次是责任方面,如果因为某一次上线导致出故障,那么故障的责任由代码作者和review人共同承担。其次是上线操作的规范化,在滴滴内部,我们总结了五条线上变更军规:提前通报要记得、变更步骤要完备、分级发布要遵守、高峰窗口要避免、服务检查要执行,每一步都通过上线发布系统确保发布人严格执行流程。 第二,反馈与响应机制的建设。计价虽然模块众多,但每个模块都有唯一的接口人负责其稳定性,各模块的接口人需要确保在模块有问题时,第一时间响应。同时我们还有oncall制度,每周都有轮值的值班人员,对整个计价系统的稳定性进行第一时间响应。 第三,每周的全员稳定性复盘。通常由本周oncall的同学向全体组员汇报本周系统的稳定性情况,分享本周系统稳定性相关情况,提高全员的稳定性意识,对于oncall期间发现的问题,需要制定解决方案及时间排期,做到问题的早发现,早排查,早解决。接下来说一下架构层面。这里介绍两点,非核心功能解耦及防御性编程。非核心功能解耦指的是不在核心流程中的功能我们都尽量将其隔离出来,避免影响到主流程,如工具类、查询类等旁支功能,在计价系统中的判定标准就是在一次实际打车过程中如果没有这个功能是否可以继续进行,为此我们解耦出了多个模块,如配置平台、dealer渲染模块、cratos开放化计价模块等等。解耦带来的好处多种多样,首先就是故障异常的解耦,解耦出来的模块其稳定性、性能甚至是逻辑问题都不会干扰核心流程,其次是当真正的故障来临时,这些非核心功能都可以做到一键降级,比如dealer渲染模块,经过降级之后就没有费用明细页,但总价依旧保留,通过这种有损的降级,我们保障了打车的核心体验依旧是完备的。防御性编程是一种系统设计思想,它是为了保证对程序的不可预见的使用不会造成程序功能上的损坏。具体在日常系统设计上有两部分,首先对所有外部依赖保持高度不信任,所有第三方依赖都需要有降级兜底方案,尤其是涉及核心功能的依赖,如数据库。在计价中,我们对大量的核心依赖都有降级兜底方案,如最重要的核心存储Codis我们有三层降级兜底,从内存、fusion再到上游透传数据,确保打车过程中即使Codis全挂,虽然可能有损但不影响核心流程的继续。其次是在日常的编码过程中,需要确保每个函数的健壮性,对于入参,不能做预设应及时返回错误。凡是可能出错的地方就一定会出错,墨菲定律告诉我们不应该心存侥幸,对于日常的编码工作,要将稳定性时常放在心上。4.2准确性在价格计算的准确性上以时间和里程的精准计算为例。在计算时间时,所有时间都经过服务端的校准,避免人为因素导致时间误差。除此之外在行程中的时间计算是通过每秒一个坐标点的上报,可以将时间的计算精度控制在秒级,而我们的计费规则只会精确到分钟级别;对于上报上来的坐标点,我们也并非全盘接受,首先相邻坐标点经过严格校验,必须符合准入规则才予以采纳,对于异常的点,系统会进行记录和报警以及时发现异常。在里程计算方面,首先两坐标点之间的距离计算并不是用直线距离计算而是使用球面距离,如下图公式所示:其次手机GPS定位可能出现漂移,系统会将每个上报过来的点进行绑路处理
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号