当前位置: 首页 > news >正文

网约车架构

20 网约车系统设计:怎样设计一个日赚 5 亿的网约车系统?

网约车的官方定义是:“以互联网技术为依托,构建服务平台,整合供需信息,使用符合条件的车辆和驾驶员,提供非巡游的预约出租汽车服务的经营活动。”通俗地说就是:利用互联网技术平台,将乘客的乘车信息发送给合适的司机,由司机完成接送乘客的服务。网约车包含专车、快车、拼车等多种形式。

中国目前网约车用户规模约5亿,我们准备开发一个可支撑目前全部中国用户使用的网约车平台,应用名称为“Udi”。

需求分析

Udi是一个网约车平台,核心功能是将乘客的叫车订单发送给附近的网约车司机,司机接单后,到上车点接乘客并送往目的地,到达后,乘客支付订单。根据平台的分成比例,司机提取一部分金额作为收益,用例图如下:

图片

Udi平台预计注册乘客5亿,日活用户5千万,平均每个乘客1.2个订单,日订单量6千万。平均客单价30元,平台每日总营收18亿元。平台和司机按3:7的比例进行分成,那么平台每天可赚5.4亿元。

另外,平台预计注册司机5千万,日活司机2千万。

概要设计

网约车平台是共享经济的一种,目的就是要将乘客和司机撮合起来,所以需要开发两个App应用,一个是给乘客的,用来叫车;一个是给司机的,用来接单。Udi整体架构如下图:

图片

相应的,Udi的系统也可以分成两个部分,一个部分是面向乘客的。乘客通过手机App注册成为用户,然后就可以在手机上选择出发地和目的地,进行叫车了。乘客叫车的HTTP请求首先通过一个负载均衡服务器集群,到达网关集群,再由网关集群调用相关的微服务,完成请求处理,如下图:

图片

网关处理叫车请求的过程是:网关首先调用订单微服务,为用户的叫车请求创建一个订单,订单微服务将订单记录到数据库中,并将订单状态设置为“创建”。然后网关调用叫车微服务,叫车微服务将用户信息、出发地、目的地等数据封装成一个消息,发送到消息队列,等待系统为订单分配司机。

Udi系统的另一部分是面向司机的,司机需要不停将自己的位置信息发送给平台,同时,还需要随时接收来自平台的指令。因此,不同于用户通过HTTP发送请求给平台,司机App需要通过TCP长连接和平台服务器保持通信,如下图:

图片

Udi司机App每3秒向平台发送一次当前的位置信息,包括当前车辆经纬度,车头朝向等。位置信息通过TCP连接到达平台的TCP连接服务器集群,TCP连接服务器集群的作用类似网关,只不过是以TCP长连接的方式向App端提供接入服务。TCP连接服务器将司机的位置信息更新到地理位置服务。

对于前面已经写入到消息队列的乘客叫车订单信息,分单子系统作为消息消费者,从消息队列中获取并处理。分单子系统首先将数据库中的订单状态修改为“派单中”,然后调用派单引擎进行派单。派单引擎根据用户的上车出发地点,以及司机上传的地理位置信息进行匹配,选择最合适的司机进行派单。派单消息通过一个专门的消息推送服务进行发送,消息推送服务利用TCP长连接服务器,将消息发送给匹配到的司机,同时分单子系统更新数据库订单状态为“已派单”。

详细设计

关于Udi的详细设计,我们将关注网约车平台一些独有的技术特点:长连接管理、派单算法、距离计算。此外,因为订单状态模型是所有交易类应用都非常重要的一个模型,所以我们也会在这里讨论Udi的订单状态模型。

长连接管理

因为司机App需要不断向Udi系统发送当前位置信息,以及实时接收Udi推送的派单请求,所以司机App需要和Udi系统保持长连接。因此,我们选择让司机App和Udi系统直接通过TCP协议进行长连接。

TCP连接和HTTP连接不同。HTTP是无状态的,每次HTTP请求都可以通过负载均衡服务器,被分发到不同的网关服务器进行处理,正如乘客App和服务器的连接那样。也就是说,HTTP在发起请求的时候,无需知道自己要连接的服务器是哪一台。

而TCP是长连接,一旦建立了连接,连接通道就需要长期保持,不管是司机App发送位置信息给服务器,还是服务器推送派单信息给司机App,都需要使用这个特定的连接通道。也就是说,司机App和服务器的连接是特定的,司机App需要知道自己连接的服务器是哪一台,而Udi给司机App推送消息的时候,也需要知道要通过哪一台服务器才能完成推送。

所以,司机端的TCP长连接需要进行专门管理,处理司机App和服务器的连接信息,具体架构如下图。

图片

处理长连接的核心是TCP管理服务器集群。司机App会在启动时通过负载均衡服务器,与TCP管理服务器集群通信,请求分配一个TCP长连接服务器。

TCP管理服务器检查ZooKeeper服务器,获取当前可以服务的TCP连接服务器列表,然后从这些服务器中选择一个,返回其IP地址和通信端口给司机App。这样,司机App就可以直接和这台TCP连接服务器建立长连接,并发送位置信息了。

TCP连接服务器启动的时候,会和ZooKeeper集群通信,报告自己的状态,便于TCP管理服务器为其分配连接。司机App和TCP连接服务器建立长连接后,TCP连接服务器需要向Redis集群记录这个长连接关系,记录的键值对是<司机ID, 服务器名>。

当Udi系统收到用户订单,派单引擎选择了合适的司机进行派单时,系统就可以通过消息推送服务给该司机发送派单消息。消息推送服务器通过Redis获取该司机App长连接对应的TCP服务器,然后消息推送服务器就可以通过该TCP服务器的长连接,将派单消息推送给司机App了。

长连接管理的主要时序图如下:

图片

如果TCP服务器宕机,那么司机App和它的长连接也就丢失了。司机App需要重新通过HTTP来请求TCP管理服务器为它分配新的TCP服务器。TCP管理服务器收到请求后,一方面返回新的TCP服务器的IP地址和通信端口,一方面需要从Redis中删除原有的<司机ID, 服务器名>键值对,保证消息推送服务不会使用一个错误的连接线路推送消息。

距离计算

乘客发起一个叫车请求时,Udi需要为其寻找合适的司机并进行派单,所谓合适的司机,最主要的因素就是距离。在[第9讲]的交友系统设计中,我们已经讨论过GeoHash算法,Udi就是直接使用Redis的GeoHash进行邻近计算。司机的位置信息实时更新到Redis中,并直接调用Redis的GeoHash命令georadius计算乘客的邻近司机。

但是Redis使用跳表存储GeoHash,Udi日活司机两千万,每3秒更新一次位置信息,平均每秒就需要对跳表做将近7百万次的更新,如此高并发地在一个跳表上更新,是系统不能承受的。所以,我们需要将司机以及跳表的粒度拆得更小。

Udi以城市作为地理位置的基本单位,也就是说,每个城市在Redis中建立一个GeoHash的key,这样,一个城市范围内的司机存储在一个跳表中。对于北京这样的超级城市,还可以更进一步,以城区作为key,进一步降低跳表的大小和单个跳表上的并发量。

派单算法

前面说过,派单就是寻找合适的司机,而合适的主要因素就是距离,所以最简单的派单算法就是直接通过Redis获取距离乘客上车点最近的空闲网约车即可。

但是这种算法效果非常差,因为Redis计算的是两个点之间的空间距离,但是司机必须沿道路行驶过来,在复杂的城市路况下,也许几十米的空间距离行驶十几分钟也未可知。

因此,我们必须用行驶距离代替空间距离,即Udi必须要依赖一个地理系统,对司机当前位置和上车点进行路径规划,计算司机到达上车点的距离和时间。事实上,我们主要关注的是时间,也就是说,派单算法需要从Redis中获取多个邻近用户上车点的空闲司机,然后通过地理系统来计算每个司机到达乘客上车点的时间,最后将订单分配给花费时间最少的司机。

如果附近只有一个乘客,那么为其分配到达时间最快的司机就可以了。但如果附近有多个乘客,那么就需要考虑所有人的等待时间了。比如附近有乘客1和乘客2,以及司机X和司机Y。司机X接乘客1的时间是2分钟,接乘客2的时间是3分钟;司机Y接乘客1的时间是3分钟,接乘客2的时间是5分钟。

如果按照单个乘客最短时间选择,给乘客1分配司机X,那么乘客2只能分配司机Y了,乘客总的等待时间就是7分钟。如果给乘客1分配司机Y,乘客2分配司机X,乘客总等待时间就是6分钟。司机的时间就是平台的金钱,显然,后者这样的派单更节约所有司机的整体时间,也能为公司带来更多营收,同时也为整体用户带来更好的体验。

这样,我们就不能一个订单一个订单地分别分配司机,我们需要将一批订单聚合在一起,统一进行派单,如下图:

图片

分单子系统收到用户的叫车订单后,不是直接发送给派单引擎进行派单,而是发给一个订单聚合池,订单聚合池里有一些订单聚合桶。订单写完一个聚合桶,就把这个聚合桶内的全部订单推送给派单引擎,由派单引擎根据整体时间最小化原则进行派单。

这里的“写完一个聚合桶”,有两种实现方式,一种是间隔一段时间算写完一个桶,一种是达到一定数量算写完一个桶。最后Udi选择间隔3秒写一个桶。

这里需要关注的是,派单的时候需要依赖地理系统进行路径规划。事实上,乘客到达时间和金额预估、行驶过程导航、订单结算与投诉处理,都需要依赖地理系统。Udi初期会使用第三方地理系统进行路径规划,但是将来必须要建设自己的地理系统。

订单状态模型

对于交易型系统而言,订单是其最核心的数据,主要业务逻辑也是围绕订单展开。在订单的生命周期里,订单状态会多次变化,每次变化都是由于核心的业务状态发生了改变,也因此在前面设计的多个地方都提到订单状态。但是这种散乱的订单状态变化无法统一描述订单的完整生命周期,因此我们设计了订单状态模型,如下图:

图片

用户叫车后,系统即为其创建一个订单,订单进入“创单”状态。然后该订单通过消息队列进入分单子系统,分单子系统调用派单引擎为其派单,订单状态进入“派单中”。派单引擎分配到司机,一方面发送消息给司机,一方面修改订单状态为“已派单”。

如果司机去接到乘客,订单状态就改为“行程中”;如果司机拒绝接单,就需要为乘客重新派单,订单重新进入消息队列,同时订单状态也改回为“派单中”;如果司机到达上车点,但是联系不到乘客,没有接到乘客,那么订单就会标记为“已取消”。如果在派单中,乘客自己选择取消叫车,订单也进入“已取消”状态。“已取消”是订单的一种最终状态,订单无法再转变为其他状态。

司机到达目的地后,通过App确认送达,订单进入“待支付”状态,等待用户支付订单金额。用户支付后,完成订单生命周期,订单状态为“已完成”。

订单状态模型可以帮助我们总览核心业务流程,在设计阶段,可以通过状态图发现业务流程不完备的地方,在开发阶段,可以帮助开发者确认流程实现是否有遗漏。

小结

在软件设计开发中,会涉及两类知识。一类是和具体业务无关的,比如编程语言、编程框架这些技术和具体业务无关,消息队列、分布式缓存这些技术也和具体业务无关。这一类技术更具有通用性,技术人员不管跳槽到哪家公司,几乎都会用到这些技术。

还有一类技术是和具体业务相关的,比如电商业务、金融业务、包括本文的网约车业务等等,这些业务如何用最合适的技术方案实现。这些和具体业务相关的技术经验主要适用于相关的业务领域。

技术人员在职业生涯的早期,需要更多地去关注和学习通用性的技术。而随着年龄增加,应该在业务相关的技术上获得更多沉淀,成为一个领域的专家,才能使自己在职场上获得更强的竞争力。

下一节我们将讨论如何使用领域驱动设计的技术方法解决业务上的问题,带你体会技术人员如何在业务上获得更多沉淀。

思考题

网约车在进行派单的时候,还需要考虑哪些因素,如何实现?

21 网约车系统重构:如何用 DDD 重构网约车系统设计?

软件开发是一个过程,这个过程中相关方对软件系统的认知会不断改变。当系统现状和大家的认知有严重冲突的时候,不重构系统就难以继续开发下去。此外,在持续的需求迭代过程中,代码本身会逐渐腐坏,变得僵硬、脆弱、难以维护,需求开发周期越来越长,bug却越来越多,系统也必须要进行重构。

我们在前一篇讨论的Udi网约车系统经过了几年的快速发展,随着业务越来越复杂,功能模块越来越多,开发团队越来越庞大,整个系统也越来越笨拙、难以维护。以前两三天就能开发完成的新功能,现在要几个星期,开发人员多了,工作效率却下降了。

Udi使用微服务架构,开始的时候业务比较简单,几个微服务就可以搞定。后面随着功能越来越多,微服务也越来越多,微服务之间的依赖关系也变得越来越复杂,常常要开发一个小功能,却需要在好几个微服务中进行修改。后来开发人员为了避免这种复杂性,倾向于把所有功能都写在一个微服务里,结果整个系统架构又开始退回到单体架构。

基于以上原因,我们准备对Udi进行一次重构,核心就是要解决微服务设计的混乱,梳理、重构出更加清晰的微服务边界和微服务之间的依赖关系。我们准备使用DDD,即领域驱动设计的方法进行这次重构。

那么,领域驱动设计的核心思想是什么?设计的一般方法是什么?如何将这些方法应用到Udi的重构过程中?这些就是我们今天要解决的主要问题。

DDD的一般方法

领域是一个组织所做的事情以及其包含的一切,通俗地说,就是组织的业务范围和做事方式,也是软件开发的目标范围。比如对于淘宝这样一个以电子商务为主要业务的组织,C2C电子商务就是它的领域。领域驱动设计就是从领域出发,分析领域内模型及其关系,进而设计软件系统的方法。

但是如果我们说要对C2C电子商务这个领域进行建模设计,那么这个范围就太大了,不知道该如何下手。所以通常的做法是把整个领域拆分成多个子域,比如用户、商品、订单、库存、物流、发票等。强相关的多个子域组成一个限界上下文,它是对业务领域范围的描述,对于系统实现而言,限界上下文相当于是一个子系统或者一个模块。限界上下文和子域共同组成组织的领域,如下:

图片

不同的限界上下文,也就是不同的子系统或者模块之间会有各种的交互合作。如何设计这些交互合作呢?DDD使用上下文映射图来完成,如下:

图片

在DDD中,领域模型对象也被称为实体。先通过业务分析,识别出实体对象,然后通过相关的业务逻辑,设计实体的属性和方法。而限界上下文和上下文映射图则是微服务设计的关键,通常在实践中,限界上下文被设计为微服务,而上下文映射图就是微服务之间的依赖关系。具体设计过程如下图:

图片

首先,领域专家和团队一起讨论分析业务领域,确认业务期望,将业务分解成若干个业务场景。然后,针对每个场景画UML活动图,活动图中包含泳道,通过高内聚原则对功能逻辑不断调整,使功能和泳道之间的归属关系变得更加清晰合理。这些泳道最终就是限界上下文,泳道内的功能就是将来微服务的功能边界,泳道之间的调用流程关系,就是将来微服务之间的依赖关系,即上下文映射图。

但是,这个状态的泳道还不能直接转化成限界上下文。有些限界上下文可能会很大,有些依赖关系可能会比较强。而一个限界上下文不应该超过一个团队的职责范围,因为根据康威定律:组织架构决定系统架构,两个团队维护一个微服务,必然会将这个微服务搞成事实上的两个微服务。所以,我们还需要根据团队特性、过往的工作职责、技能经验,重新对泳道图进行调整,使其符合团队的职责划分,这时候才得到限界上下文。

在这个限界上下文基础上,考虑技术框架、非功能需求、服务重用性等因素,进一步进行调整,就得到最终的限界上下文设计,形成我们的微服务架构设计。

我们将遵循上述DDD方法过程对Udi微服务进行重新分析设计,并进行系统重构。

Udi DDD 重构设计

首先分析我们的业务领域,通过头脑/事件风暴的形式,收集领域内的所有事件/命令,并识别事件/命令的发起方即对应的实体。最后识别出来的实体以及相关活动如下表:

图片

基于核心实体模型,绘制实体关系图,如下:

图片

在实体间关系明确且完整的前提下,我们就可以针对各个业务场景,绘制场景活动图。活动图比较多,这里仅用拼车场景作为示例,如下:

图片

依据各种重要场景的活动图,参考团队职责范围,结合微服务重用性考虑及非功能需求,产生限界上下文如下表:

图片

针对每个限界上下文进一步设计其内部的聚合、聚合根、实体、值对象、功能边界。以订单限界上下文为例:

图片

上述订单实体的属性和功能如下表:

图片

最后,在实现层面,设计对应的微服务架构如下图:

图片

这是一个基于领域模型的分层架构,最下层为聚合根对象,组合实体与值对象,完成核心业务逻辑处理。上面一层为领域服务层,主要调用聚合根对象完成订单子域的业务,根据业务情况,也会在这一层和其他微服务通信,完成更复杂的、超出当前实体职责的业务,所以这一层也是一个聚合层。

再上面一层是应用服务层,将实体的功能封装成各种服务,供各种应用场景调用。而最上面是一个接口层,提供微服务调用接口。

小结

领域驱动设计很多时候雷声大,雨点小,说起来各种术语满天飞,真正开发实践的时候又无从下手。这节的案例来自一个真实落地的DDD重构设计文档,你可以参考这个文档,按图索骥,应用到自己的开发实践中。

既然说到“按图索骥”,那我认为也有必要在这一节的最后,帮你画一个更有概括性的DDD重构路线图,我们把使用DDD进行系统重构的过程分为以下六步:

  1. 讨论当前系统存在的问题,发现问题背后的根源。比如:架构与代码混乱,需求迭代困难,部署麻烦,bug率逐渐升高;微服务边界不清晰,调用依赖关系复杂,团队职责混乱。
  2. 针对问题分析具体原因。比如:微服务 A 太庞大,微服务B和C职责不清,团队内业务理解不一致,内部代码设计不良,硬编码和耦合太多。
  3. 重新梳理业务流程,明确业务术语,进行DDD战略设计,具体又可以分为三步。- a. 进行头脑风暴,分析业务现状和期望,构建领域语言;- b. 画泳道活动图、结合团队特性设计限界上下文;- c. 根据架构方案和非功能需求确定微服务设计。
  4. 针对当前系统实现和DDD设计不匹配的地方,设计微服务重构方案。比如:哪些微服务需要重新开发,哪些微服务的功能需要从A调整到B,哪些微服务需要分拆。
  5. DDD技术验证。针对比较重要、问题比较多的微服务进行重构打样,设计聚合根、实体、值对象,重构关键代码,验证设计是否合理以及团队能否驾驭DDD。
  6. 任务分解与持续重构。在尽量不影响业务迭代的前提下,按照重构方案,将重构开发和业务迭代有机融合。

思考题

你认为DDD最大的价值是什么?如何才能成功落地DDD?

22 大数据平台设计:如何用数据为用户创造价值?

现在,业界普遍认为互联网创新已经进入下半场,依靠技术创新或者商业模式创新取得爆发性发展的机会越来越少。于是大家把目光转向精细化运营,主要手段就是依靠大数据技术,挖掘每个用户独特的商业价值,提供更具个性化的服务,以此来提升服务水平和营收能力,最终获得更强的市场竞争能力。

Udi大数据平台的主要目标是根据用户的不同喜好,为其分配不同的车型,一方面改善用户体验,另一方面也增加平台营收。此外,如何为用户推荐最优的上车点和下车点,如何分析订单和营收波动,如何发现潜在的高风险用户等等,也需要依赖大数据平台。

大数据技术不同于我们前面设计的高并发案例,高并发案例虽然也要处理海量用户的请求,但是每个用户请求都是独立的,计算与存储也是每个用户独立进行的。而大数据技术则要将这些海量的用户数据进行关联计算,因此,适用于高并发架构的各种分布式技术并不能解决大数据的问题。

Udi大数据平台设计

根据Udi大数据应用场景的需求,需要将手机App端数据、数据库订单和用户数据、操作日志数据、网络爬虫爬取的竞争对手数据统一存储到大数据平台,并支持数据分析师、算法工程师提交各种SQL语句、机器学习算法进行大数据计算,并将计算结果存储或返回。Udi大数据平台架构如下图:

图片

大数据采集与导入

Udi大数据平台整体可分为三个部分,第一个部分是大数据采集与导入。这一部分又可以分为4小个部分,App端数据采集、系统日志导入、数据库导入、爬虫数据导入。

App端除了业务功能模块,还需要包含几个数据埋点上报模块。App启动的时候,应用启动上报模块会收集用户手机信息,比如手机型号、系统版本、手机上安装的应用列表等数据;App运行期间,也会通过定时数据上报模块,每5秒上报一次数据,主要是用户当前地理位置数据;用户点击操作的时候,一方面会发送请求到Udi后端应用系统,一方面也会通过用户操作上报模块将请求数据以及其他一些更详细的参数发送给后端的应用上报服务器。

后端的应用上报服务器收到前端采集的数据后,发送给消息队列,SparkStreamin从消息队列中消费消息,对数据进行清洗、格式化等ETL处理,并将数据写入到HDFS存储中。

Udi后端应用系统在处理用户请求的过程中,会产生大量日志和数据,这些存储在日志系统和MySQL数据库中的数据也需要导入到大数据平台。Flume日志收集系统会将Udi后端分布式集群中的日志收集起来,发送给SparkStreaming进行ETL处理,最后写入到HDFS中。而MySQL的数据则通过Sqoop数据同步系统直接导入到HDFS中。

除了以上这些Udi系统自己产生的数据,为了更好地应对市场竞争,Udi还会通过网络爬虫从竞争对手的系统中爬取数据。需要注意的是,这里的爬虫不同于[04讲]中的爬虫,因为竞争对手不可能将订单预估价等敏感数据公开。因此,爬虫需要模拟成普通用户爬取数据,这些爬来的数据也会存储在HDFS中,供数据分析师和产品经理在优化定价策略时分析使用。

大数据计算

Udi大数据平台的第二个部分是大数据计算。写入到HDFS中的数据,一方面供数据分析师进行统计分析,一方面供算法工程师进行机器学习。

数据分析师会通过两种方式分析数据。一种是通过交互命令进行即时查询,通常是一些较为简单的SQL。分析师提交SQL后,在一个准实时、可接受的时间内返回查询结果,这个功能是通过Impala完成的。另外一种是定时SQL统计分析,通常是一些报表类统计,这些SQL一般比较复杂,需要关联多张表进行查询,耗时较长,通过Hive完成,每天夜间服务器空闲的时候定时执行。

算法工程师则开发各种Spark程序,基于HDFS中的数据,进行各种机器学习。

以上这些大数据计算组件,Hive、Spark、SparkStreaming、Impala都部署在同一个大数据集群中,通过Yarn进行资源管理和调度执行。每台服务器既是HDFS的DataNode数据存储服务器,也是Yarn的NodeManager节点管理服务器,还是Impala的Impalad执行服务器。通过Yarn的调度执行,这些服务器上既可以执行SparkStreaming的ETL任务,也可以执行Spark机器学习任务,而执行Hive命令的时候,这些机器上运行的是MapReduce任务。

数据导出与应用

Udi大数据平台的第三个部分是数据导出与应用。Hive命令执行完成后,将结果数据写入到HDFS中,这样并不方便数据分析师或者管理人员查看报表数据。因此还需要用Sqoop将HDFS中的数据导出到MySQL中,然后通过数据分析查询控制台,以图表的方式查看数据。

而机器学习的计算结果则是一些学习模型或者画像数据,将这些数据推送给推荐引擎,由推荐引擎实时响应Udi系统的推荐请求。

大数据平台一方面是一个独立的系统,数据的存储和计算都在其内部完成。一方面又和应用系统有很多关联,数据需要来自应用系统,而计算的结果也需要给应用系统使用。上面的架构图中,属于大数据平台的组件我用蓝色标出,其他颜色代表非大数据平台组件或者系统。

Udi大数据派单引擎设计

我们在第20讲讨论了Udi派单引擎,这个派单引擎并没有考虑乘客和车型的匹配关系。根据Udi的运营策略,车辆新旧程度、车辆等级与舒适程度、司机服务水平会影响到订单的价格。派单成功时,系统会根据不同车辆情况预估不同的订单价格并发送给乘客,但是有些乘客会因为预估价格太高而取消订单,而有些乘客则会因为车辆等级太低而取消订单,还有些乘客则会在上车后因为车辆太旧而给出差评。

Udi需要利用大数据技术优化派单引擎,针对不同类别的乘客匹配尽可能合适的车辆。上面采集了乘客的手机型号及手机内安装应用列表,订单数据记录了乘客上下车地点,乘客评价以及订单取消原因记录了用户乘车偏好,车辆及司机数据记录了车辆级别和司机信息,这些数据最终都会同步到大数据平台。

我们将利用这些数据优化Udi派单引擎。根据用户画像、车辆画像、乘车偏好进行同类匹配。

基于乘客分类的匹配

根据乘客的注册信息、App端采集的乘客手机型号、手机内安装应用列表、常用上下车地点等,我们可以将乘客分类,然后根据同类乘客的乘车偏好,预测乘客的偏好并进行匹配。

图片

比如根据数据分类,乘客A和乘客C是同类乘客,而乘客A偏好车辆类型B和D。乘客C叫车的时候,那么派单系统会优先给他派单车辆类型B和D。

基于车辆分类的匹配

事实上,我们可以直接根据车辆类型属性,对车辆类型进行再分类。比如通过机器学习统计分析,车辆类型B和D可以归为一类,那么如果乘客C偏好车辆类型B,那么我们可以认为车辆类型D也匹配他。

图片

使用推荐引擎对派单系统进行优化,为乘客分配更合适的车辆,前提是需要对用户和车辆进行分类与画像,想要完成这部分工作,我们可以在大数据平台的Spark机器学习模块通过聚类分析、分类算法、协同过滤算法,以及Hive统计分析模块进行数据处理,将分类后的数据推送给派单引擎去使用。

派单引擎在原有的最小化等车时间基础上,对派单进行调整,使车辆和乘客偏好更匹配,改善用户体验,也增加了平台营收。

小结

网约车是一个格外依赖大数据进行用户体验优化的应用。比如用户上车点,在一个几千平方米的POI区域内,乘客方便等车,司机不违章的地点可能只有一两个,这一两个点又可能在任何地图上都没有标示。这就意味着,司机和乘客需要通过电话沟通很久才知道对方说的上车点在哪里,然后要么乘客徒步几百米走过来,要么司机绕一大圈去接,给司机和乘客都造成很多麻烦,平台也会因此流失很多用户。

对于这种问题,电子地图应用的厂商需要派测绘人员现场标注这些点。而对于网约车平台,由于不停在上传司机的位置信息,只需要根据乘客最后的上车点进行聚类分析,就会发现该区域大部分乘客最后都是在某个点上车,这个点就是最佳上车点。也就是说,只需要最初的一批乘客忍受麻烦,他们的行为数据就可以被网约车平台用于机器学习和数据挖掘,并被用于优化用户体验。

网约车平台像这样依赖大数据的地方还有很多。所以,网约车平台需要尽可能获取、存储用户和司机的各种行为与业务数据,并基于这些数据不断进行分析、挖掘,寻找潜在的商业机会和用户体验优化。对于一个数亿用户规模的网约车平台,这些数据的规模是非常庞大的,因此需要一个强大、灵活的大数据平台才能完成数据的存储与计算。

思考题

在你的工作中,是否有涉及到大数据和机器学习,它们带来了哪些价值?

http://www.dtcms.com/a/418664.html

相关文章:

  • K8s StorageClass配置实战:从入门到精通
  • 鼻毛修剪器MCU方案开发设计
  • 为什么LLM会使用到向量这种数学工具?
  • LocalStorage Token vs HttpOnly Cookie 认证方案
  • ArkUI V2中Repeat组件使用注意事项总结
  • 自动字幕翻译避坑指南
  • Go vs. PHP:核心优势劣势对比
  • Go 语言中的**数组 (Array)*用法
  • php 网站部署虚拟主机安装wordpress
  • 浙江省旅游企业网站建设情况做最最优秀的视频网站有哪些
  • 设计模式第五章(门面模式)
  • 海康相机SDK封装
  • 大模型应用:一个基于AI大模型的自动邮件简报系统 - Flask + HTML 方案
  • 开源 C# 快速开发(八)通讯--Tcp服务器端
  • MTK调试-电池识别
  • 网站目标网页制作下载图片代码
  • 钱站网站如何建设手机移动网站
  • Vue调用浏览器打印
  • 捷讯官网 网站建设网站到期只续域名不续空间能打开吗
  • CS231n学习笔记1-4: Image Features
  • DragonBalls_One009*
  • extern关键字
  • 捷为科技亮相新能源汽车产业对接会,数智化平台赋能汽车行业高质量发展
  • ChatBI 学习
  • 百度网站推广咨询建筑网人才
  • 桂林网站建设服务网站定制牛七科技
  • WebRTC 发送端 SSRC 生成流程总结
  • 客户标签自动管理:标签自动化运营,画像持久保鲜
  • 云原生架构与GitOps技术栈介绍
  • 智能外呼产品架构组成