Uber系统架构设计

400次阅读  |  发布于2年以前

Uber 一开始是单体架构,后来逐渐演化为面向服务的架构。Uber 最早只为旧金山提供服务,他们称之为 UberBlack。后来随着核心领域模型的增长以及引入了越来越多的新特性,组件的耦合非常严重,持续集成变成了沉重的负担,每次部署都意味着需要一次性部署所有的东西。在单一代码库中添加新功能、修复 bug、解决技术债务变得非常困难,这也是为什么 Uber 后来采用面向服务的架构的原因,这也促使 Uber 工程团队重构了新的 Uber 应用。

新应用程序增加了 UberPool、预约出行和促销车辆的视图。

目标

  1. 实现优步核心出行体验 99.99%的可靠性(每年最多 1 小时的停机时间,每周最多 1 分钟,换句话说,每 10000 次运营一次只能出现 1 次故障)
  2. 代码库拆分成两部分:核心代码和可选代码。核心代码被用于乘客注册、呼叫、完成或取消出行要求时,任何对核心代码的修改都必须经过严格的审查。可选代码很少被审查,并且可以在任何时候被动态关闭。这鼓励了代码级别上的相互独立,允许我们尝试新特性并随时停止它们。
  3. 核心架构:类名、业务逻辑单元之间的继承关系、主业务逻辑、插件点(名称、依赖关系、结构等)、响应式编程链(响应式编程之间的关系)、统一平台组件(统一的平台级模块)

解决方案

  1. 应用 iOS 架构(从 MVC 到 VIPER,并创建 Riblets)

功能性需求

  1. 乘客可以查看附近的司机
  2. 乘客可以发起乘车请求
  3. 乘客可以查看司机的预计到达时间和预计价格
  4. 司机如果接受请求,直到整个行程结束,乘客都可以查看司机的位置并与之沟通
  5. 乘客可以预定出租车
  6. 可以自动匹配乘客和司机
  7. 可以看到附近的出租车
  8. 位置跟踪
  9. 事后操作:评价、发送电子邮件、更新数据库、付款
  10. 价格和激励:在预测算法的帮助下,当需求增加而供给减少时,价格会上升。据 Uber 称,激励有助于满足供给需求,通过提高价格,当需求增加时,路上会有更多的出租车。

非功能性需求

  1. 全球化
  2. 低时延
  3. 高可用
  4. 高一致性
  5. 可扩展性
  6. 数据中心故障:用于处理意外的级联故障或上游网络提供商的失效。Uber 维护了一个备份数据中心,交换机已经准备好将所有数据都路由到备份数据中心,唯一的问题是正在进行的行程的数据可能没有备份。


DISCO — Uber 系统的基础

  1. 供给服务(在司机端操作)
  2. 请求服务(在乘客端操作)

调度优化(或称 DISCO,Dispatch optimization)是 Uber 系统的一部分,用于基于位置数据匹配需求和供给。在匹配司机和乘客时,DISCO 保持最小化总服务时间和驾驶时间。与简单地使用纬度和经度来定位乘客和司机不同,DISCO 使用了更精确的谷歌 S2 库,它将地图划分为多个小单元。例如根据需求,可以在地图上设置 1 平方公里的单元格,每个单元分配唯一的 ID,因此在分布式系统中可以通过 ID 更方便的存储和访问单元数据,并且可以使用一致性哈希来存储单元数据。

调度系统基于 NodeJS 实现,提供基于事件的异步机制,允许在任何时候通过 WebSocket 和应用程序进行交互。Uber 使用一致性哈希环来扩展其 DISCO 服务器,从而在服务器之间有效分配负载,并自动检测集群中是否有新节点被添加或是否有节点从集群中移除,从而通过 SWIM/Gossip 协议重新分配工作负载。服务器之间通过 RPC 进行通信。

请求服务

供给服务

DISCO — 调度优化

  1. 减少司机驾驶时间
  2. 减少乘客等待时间
  3. 最小化总服务时间

出行数据

数据库架构

系统架构


系统组件

地图 — 把出租车位置发送给乘客

Web 应用防火墙

负载均衡

Kafka

Web Sockets

Hadoop

基于 MySQL 的支付数据库

Spark 流处理集群

司机资料引擎

欺诈引擎

Kibana/Graphana - Elastic search

最后,

大数据

大数据是一个必须要发展的更好的解决方案。

出处:https://xie.infoq.cn/article/c7c4c0fb77b70d1ea3c8c5e0b

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8