Uber实时调度平台系统的架构概要

Uber通过其在线调度平台能自动对乘客和车辆进行适配,大大提高了城市交通效率。其首席架构师Matt Ranney最近透露了其调度系统的概要,其系统是如何将乘客和司机进行配对的。

Uber Unveils its Realtime Market Platform

Ranney解释了重写系统的原因,描述了该平台架构原理,它的特点是可用性和性能,还有一些算法实现以及为什么Uber决定设计自己的RPC协议。

老的调度系统是专为私车和其周围需要坐车的人们打造的,但是Uber想进入货运等新市场,另外调度系统也有多点故障,难以跟上Uber快速增长。

新的调度系统主要有两个服务:供应司机和乘客招车需求,这些服务会跟踪供应和需求所有的能力和状态机。例如,供应服务会知道一个车辆有几个座位适合乘坐或是否容纳残疾轮椅。调度系统也第三个服务,称为Disco(调度优化),其主要功能是匹配供应和需求,Disco会让Uber展望未来,比如,老的调度系统只看到目前的供应量,因为大部分车辆都很忙,这个新的优化能够让Uber维持一个全局指数,新系统更有效率,也需要更多数据,Uber希望新系统能够处理每秒1百万写操作和更高的读操作,因此需要shard分片数据。

为了完成这种扩展,Uber使用Google的S2 Geometry Library,S2能够将球体分为小区cell,每个小区有一个id,地球大致是一个球形。S2有两个重要特性:它能够定义每个cell的分辨率,它能发现需要覆盖区域的cell。Uber使用3,31平方公里的cell来分片其数据。所有这些让Uber降低乘客等待时间,司机的额外驾驶以及到达乘客招车点的时间(ETA),当一个乘客使用Uber会发生什么?Uber会使用乘客的当时地理位置和S2的面积覆盖函数来寻找其周围适配的司机,Uber然后选择更短的ETA, Uber寻找的不仅是可搭载乘客的司机,而且还包括那些正在行驶到目标地可搭顺路车的司机。

整个调度系统使用的是NodeJS,这是一个单线程,为了充分利用一台服务器的多核,也很容易在其上启动新Node(大概是多个Node跑在一台机器上),Ranney指出其服务器需要是有状态的,否则单靠数据存储是无法应付负载访问的,无论这些状态是运行在同一机器上或者不是,他们已经建立了ringpop来处理这个问题,Ringpop使用一致性哈希环,这也是被Amazon的Dynamo、memcached或Riak使用的。为了能够跨节点分布状态,为了管理集群成员和失败侦测,Ringpop使用SWIM,这是一个可扩展的弱一致性,感染风格的过程组成员协议,它和Hashicorp的 Serf是同样的gossip协议,Ringpop使用TChannel作为其RPC协议。

TChannel是受Twiiter Finagle的多路复用RPC协议Mux启发,Uber需要创建一个自己的西医,主要因为需要支持多种语言如Javascript和python,跟踪与封装,Ranny说Uber已经从HTTP+JSON迁移到基于TChannel的Thrift,TChannel在Node.js中比HTTP快20倍。

Uber首席架构师Ranny还介绍了Uber在可靠性、数据中心、运营维护方面经验。

最后,Ranny说:调度系统大部分是基于Node.js建立,他们会迁移到io.js,这是一个Node.js分支与竞争者。他们的地图和ETA使用C++和Java几种语言编写,由于需要继承各种不同的服务,他们的所有业务逻辑使用Python编写,他们还建立了自己的面向列族的分布式存储,也使用了Postgres, Redis, MySQL 和Riak