程序员社区

Uber系统设计(Part 1)

Uber系统设计(Part 1)插图

原文地址

Uber系统设计(Part 1)插图1

优步的技术看起来很简单,当用户通过应用程序请求打车时,司机会来接他们到目的地。然而,在这背后,是由数千个服务和TB级数据组成的庞大基础设施来支持平台上的每一次打车服务。

像大多数基于网络服务一样,优步的后端系统一开始是一个“单体”软件架构,包含一堆应用服务器和一个单一的数据库。
如果你在找Uber的软件架构设计可以观看YouTube视频

系统主要是基于python来开发的,以及使用SQLAlchemy作为数据库的ORM层。刚开始的架构,在少数城市提供一定数量的打车服务是没问题的。

2014年后,架构演化为面向服务(SOA)的体系结构,拥有大约100个服务。现在优步的后端不仅设计为处理出租车服务,还可以处理包括出租车之外的、送食品和货物服务。

后端主要服务于移动手机流量。优步应用程序通过移动数据与后台通信。

最具挑战性的是需求不断在变!

优步的调度系统就像一个实时市场交易平台,通过手机将司机和乘客匹配起来。因此需要两个服务:
1、车辆供应服务(supply service)
2、乘车需求处理服务(demand service)
接下来,我在解释时使用:出租车的供应和乘客的需求

供应服务

  • 供应服务根据地理位置(经纬度)来跟踪车辆,每5秒钟向服务端发送一次经纬度信息。
  • 所有供应的状态保存在内存中
  • 为了跟踪车辆需要对车子很多属性建模:车的座位个数、车类型、是否有儿童座椅等。
  • 车辆空座位的情况跟踪。例如,一辆车可能有三个座位,但其中两个已经有人了。

乘客需求服务

  • 当乘客请求打车时,需求服务会跟踪乘客的GPS位置。
  • 它可以跟踪订单的要求,如乘客需要小型车/大车等
  • 乘客的需求必须和能供应服务的车辆状况匹配。
    现在我们有了供给和需求。打车软件所需要的就一个功能,就是实现车辆供应和乘客需求的配对,这种功能在UBER中被称为DISCO。

DISCO-DISPATCH optimization(派单优化)

该服务运行在数百个进程上。调度系统的核心要求:
1、减少不必要的驾车路程
2、减少等待时间
3、缩短达到目的地时间

派单系统是如何工作的?怎么匹配司机?

GPS/位置数据驱动调度系统工作,这意味着我们必须对地图和位置数据进行建模。
1、地球是一个球体。仅仅基于经度和纬度很难来做汇总和近似。所以优步用谷歌S2库把地球分成小单元。每个单元格都有一个唯一的单元格ID。
2、S2可以根据形状圈出范围。如果你想画一个以伦敦为中心,半径为1公里的圆,S2可以告诉你需要哪些单元格来完全覆盖这个形状。

Uber系统设计(Part 1)插图2

1、因为每个单元格都有一个ID,所以ID被用作分片的键。当车辆出现在某个位置,其对应的单元ID就可以确定。使用单元ID作为分片的键,更新车辆的位置。然后,它被发送到几个副本。
2、为了匹配乘客和司机,或者只是在地图上显示汽车,DISCO通过supply服务发送位置信息。
3、 系统根据乘客的GPS数据,使用地图圆形区域包含的所有单元ID,找出覆盖的车辆。然后根据乘客的需求过滤无效车辆。
4、将车辆列表和客户需求发送到ETA服务,计算出能最快接到乘客的车子进行匹配。
5、通过Supply系统将匹配结果发送给司机。
如何扩展派单系统?
1、派单系统是使用node.js构建的,使用node的优点是异步和基于事件的框架。同时,它允许你通过WebSockets发送和接收消息。
2、所以客户端可以随时发送消息给服务器,或者服务器可以随时发送消息给客户端。
3、如何分配派单在同一台机器上和到多台机器?
4、可扩展的解决方案是使用Node js与ringpop,它是基于gossip使用SWIM协议和一致性hash环实现快速RPC协议。
5、Ringpop是一个为分布式应用程序提供合作和协调的库。它在成员协议上维护一致性hash环,为了路由方便提供请求转发。它可用于应用程序分片具有可扩展和容错性。
6、SWIM:可伸缩的弱一致性传染式进程组成员协议
7、使用gossip添加和删除节点很容易,因此扩展也很容易。
8、Gossip协议,SWIM、健康检查,成员变化都是协议一部分。
后面第二部分将介绍打车的路线规划、系统负载均衡,kafa的使用等内容。

赞(0) 打赏
未经允许不得转载:IDEA激活码 » Uber系统设计(Part 1)

一个分享Java & Python知识的社区