Uber 系统架构设计

本文涉及的产品
网络型负载均衡 NLB,每月750个小时 15LCU
应用型负载均衡 ALB,每月750个小时 15LCU
传统型负载均衡 CLB,每月750个小时 15LCU
简介: Uber 系统架构设计

共享租车鼻祖 Uber 的后端架构也经历了从单体到微服务的演化过程,这篇文章介绍了 Uber 后端架构的功能、设计,对于理解 O2O 系统的架构实现提供了很好的参考。原文:Uber System Architecture[1]


image.png

Fikri Rasyid@Unsplash


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


延伸阅读:

  1. Is Microservice Architecture the best choice for Machine Learning Deployment: https://towardsdatascience.com/is-microservice-architecture-the-best-choice-for-machine-learning-deployment-39ae325a2baf
  2. Engineering the Architecture Behind Uber's New Rider App: https://eng.uber.com/new-rider-app-architecture/


image.png


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


目标


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


解决方案


image.png


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


延伸阅读:

  1. iOS Architecture Patterns: https://medium.com/ios-os-x-development/ios-architecture-patterns-ecba4c38de52
  2. Ensuring Product Success With Transparency: https://mutualmobile.com/approach

功能性需求


image.png


image.png


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


非功能性需求


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


延伸阅读:

How to Make an App Like Uber: https://mlsdev.com/blog/how-to-make-an-app-like-uber


image.png

image.png




DISCO — Uber 系统的基础


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

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

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


请求服务


  • 乘客请求搭乘出租车
  • 可以获得乘客发起请求的位置
  • 微服务通过 WebSocket 获取乘客发起的请求
  • 跟踪乘客的 GPS 位置
  • 接受乘客的特定需求
  • 将请求以及其他需求移交给调度系统,以将其连接到供给服务


供给服务


  • 为司机端提供服务
  • 使用经纬度数据(地理位置)跟踪出租车
  • 所有在线的出租车每 5 秒过 Web 应用程序防火墙向负载均衡器发送一次它们的位置
  • 负载均衡器将出租车的 GPS 位置定向到 Kafka REST API。
  • 出租车的位置信息被更新到 Kafka,同时副本被发送到数据库和 DISCO,这样每个服务都可以使用最新的出租车位置信息

DISCO — 调度优化


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


出行数据


  • 出租车位置数据
  • 出行完成后的计费数据,包括出行开始和结束的时间戳,这样 Uber 可以计算车费并向乘客收费

数据库架构


  • 支持应用频繁读写
  • 因为出租车每 5 秒更新一次位置信息,因此会有频繁的写操作。同时有很多出行请求,意味着读操作也会很频繁。
  • 从关系型数据库 PostgreSQL 到建立在 MySQL 之上的无模式 NoSQL 数据库

系统架构


image.png


延伸阅读:


  1. System Design: Uber Lyft ride sharing services: https://youtu.be/J3DY3Te3A_A
  2. Uber System Design: https://youtu.be/NOHQ15lwHKY
  3. Grokking the Uber System Design Interview: https://youtu.be/AAMLzNaDkjk
  4. Uber System Design: https://youtu.be/Tp8kpMe-ZKw
  5. UBER System Design: https://youtu.be/umWABit-wbk



image.png




系统组件


image.png


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


  • 乘客发出出行请求,应用程序会在地图上显示附近所有司机的位置。当客户打开地图时,会向服务器发送查找附件所有司机的查询。
  • Kafka 提供的实时位置数据将用于计算司机到达时间,这样乘客就可以知道车辆什么时候会来,同时还会告诉乘客到达目的地的预计时间。
  • Dijkstra 算法可以用来在有公路网的地图上找到最短路径。由于最短路径(按距离计算)并不总是最快路径(繁忙的交通可能会影响到达时间),更复杂的人工智能算法也可以用来估算最短行驶时间。


Web 应用防火墙


  • 出于安全原因会设置防火墙,用来拦截来自可疑来源或服务不支持地区的请求。


负载均衡


  • Uber 使用三层负载均衡器,分别用于处理网络的三层、四层和七层协议。L3 是基于 IP 的负载均衡,L4 用于基于 DNS 的负载均衡,L7 处理应用程序负载均衡。


Kafka


  • Kafka 为 Uber 提供了日志层。它可以立即将更新记录到某个存储位置,从而可以被不同微服务使用。Kafka 提取所有这些实时更新并保证没有信息丢失。在实现上,通过一个 Kafka 服务器集群来达成这个目的。


Web Sockets


  • 在这种类型的应用程序中,客户端(包括乘客应用和司机应用)和服务器之间的通信可以通过 Web Sockets 来完成,从而可以保持客户端与服务器之间的长连接。


Hadoop


  • Uber 通过分析数据来改善服务。Kafka 会定期在 Hadoop 中存储和归档数据,这些数据在分析应用程序的不同使用趋势时很有帮助。例如,可以知道何时何地有更多的 Uber 司机或更多的出行请求。


基于 MySQL 的支付数据库


  • 支付服务基于 Kafka,在出行服务完成后被触发。一旦出行完成,基于距离、时间等信息,计算出需要支付金额,并将所有这些信息插入支付 MySQL 数据库中。如果需要的话,支付服务也将与支付网关对接。此外还提供开放 API,以供查询客户或司机帐户所有与支付相关的信息。
  • 支付选项,方便用户添加新的支付配置文件
  • 对交易进行支付预授权,保证有一定数量的金额可供支付
  • 取消付款,退款
  • 获取客户账户并收费,将金额从用户账户转移到 Uber
  • 删除支付选项和配置文件
  • 小费
  • 预约服务
  • 促销
  • 按期清偿未付款项
  • 在服务期间切换支付方式
  • 默认支付方式,支持回退或选择
  • 重复支付
  • 不正确的货币转换
  • 错误的付款
  • 缺失的付款
  • 空授权


延伸阅读:

Uber's Payment Platform: https://underhood.blog/uber-payments-platform


image.png

image.png

image.png

image.png

image.png

Spark 流处理集群


  • 跟踪基本事件,例如找不到司机,识别缺少司机的区域,以及其他基本分析。Spark 集群还会转储 Hadoop 集群中的所有事件,以便进行进一步分析,如用户分析、司机行为分析等,从而可以将客户或司机划分为高级、常规等不同等级。


司机资料引擎


  • 基于评价、服务时间精度等信息对司机进行分类


欺诈引擎


  • 如果同一司机总是接同一用户的单子,他们很有可能是朋友,或者他试图利用 Uber 提供的激励计划。我们还可以使用相同的数据来获取交通或道路状况信息,从而进一步支持地图服务。


Kibana/Graphana - Elastic search


  • 日志分析
  • 跟踪 HTTP API,管理配置文件,收集反馈和评价,促销和优惠券,欺诈检测,支付欺诈,激励滥用,被盗账户

最后,


大数据


延伸阅读:

Uber's Big Data Platform: 100+ Petabytes with Minute Latency: https://eng.uber.com/uber-big-data-platform/


从这篇文章中可以看出,大数据是一个必须要发展的更好的解决方案。


image.png


image.png


image.png

延伸阅读:

  1. https://techtakshila.com/system-design-interview/chapter-3/#high-level-design
  2. https://tianpan.co/hacking-the-software-engineer-interview#designing-uber-or-a-realtime-marketplace
  3. https://weixia.info/ride-hailing-system-design.html
  4. https://www.codekarle.com/system-design/Uber-system-design.html
  5. https://underhood.blog/uber-payments-platform
  6. https://github.com/raghav-chamarthy/Uber-replica
  7. https://github.com/apache/hudi
  8. https://eng.uber.com/engineering-routing-engine/
  9. https://www.garyfox.co/uber-business-model/
  10. https://eng.uber.com/michelangelo-machine-learning-platform/


References:

[1] Uber System Architecture: https://medium.com/interviewnoodle/uber-system-architecture-40201134aaea

目录
相关文章
|
2月前
|
存储 分布式计算 关系型数据库
架构/技术框架调研
本文介绍了微服务间事务处理、调用、大数据处理、分库分表、大文本存储及数据缓存的最优解决方案。重点讨论了Seata、Dubbo、Hadoop生态系统、MyCat、ShardingSphere、对象存储服务和Redis等技术,提供了详细的原理、应用场景和优缺点分析。
|
4月前
|
存储 监控 数据挖掘
Kylin使用心得与实战经验分享
本文详细介绍了Apache Kylin的使用方法及其在大数据分析中的优势。首先,Kylin是一款基于Hadoop和Spark的开源分布式分析引擎,通过预计算技术实现亚秒级的交互式查询响应,大幅提高数据分析效率。接着,文章阐述了Kylin的核心特点,包括高效多维分析能力和预计算与实时查询的平衡。然后,详细说明了环境搭建、配置步骤及示例代码,展示了如何配置HBase存储后端。在数据建模与优化部分,讲解了星型模型和雪花模型的选择,以及分区策略和索引优化技巧。
|
7月前
|
存储 数据采集 数据挖掘
“湖仓一体架构及其应用”写作框架,系统架构设计师
随着5G、大数据、人工智能、物联网等技术的不断成熟,各行各业的业务场景日益复杂,企业数据呈现出大规模、多样性的特点,特别是非结构化数据呈现出爆发式增长趋势。在这一背景下,企业数据管理不再局限于传统的结构化OLTP(On-Line Transaction Processing)数据交易过程,而是提出了多样化、异质性数据的实时处理要求。传统的数据湖(Data Lake)在事务一致性及实时处理方面有所欠缺,而数据仓库(Data Warehouse)也无法应对高并发、多数据类型的处理。因此,支持事务一致性、提供高并发实时处理及分析能力的湖仓一体(Lake House)架构应运而生。湖仓一体架构在成本、
156 2
|
分布式计算 Kubernetes Java
「技术选型」工作流引擎哪家强?首席架构帮你挑
「技术选型」工作流引擎哪家强?首席架构帮你挑
|
消息中间件 SQL 数据采集
解决研发数据分析瓶颈,开源项目 DevLake 加入 Apache 软件基金会孵化器 | InfoQ 专访
每一位开源参与者、每一个开源项目都可以成为舞台上的主角。
294 0
解决研发数据分析瓶颈,开源项目 DevLake 加入 Apache 软件基金会孵化器 | InfoQ 专访
|
Java 大数据 程序员
Framework掌握不熟?字节跳动大牛带你系统化学习
面试中Framework与Binder的重要性 Framework 通常作为一个Android APP开发者,我们并不关心Android的源代码实现,不过随着Android开发者越来越多,企业在筛选Android程序员时越来越看中一个程序员对于Android底层的理解和思考,这里的底层主要就是Android Framewok中各个组件的运行原理,例如Binder的运行机制、ServiceManager的作用等等。
Framework掌握不熟?字节跳动大牛带你系统化学习
|
SQL 弹性计算 分布式计算
【有奖调研】E-MapReduce 易用性有奖调研
为深刻理解您的需求,提升 EMR 产品与服务能力。阿里云 EMR 团队诚邀您参加 EMR 易用性调研。我们会认真评估您提出的每一条建议,并从中筛选出优质回复回赠精美礼品。
243 0
【有奖调研】E-MapReduce 易用性有奖调研
|
SQL 机器学习/深度学习 资源调度
重磅!《Apache Flink 十大技术难点实战》发布,帮你从容应对生产环境中的技术难题
总结生产环境十大常见难点,10篇技术实战文章帮你完成故障识别、问题定位、性能优化等全链路过程,实现从基础概念的准确理解到上手实操的精准熟练,从容应对生产环境中的技术难题!
重磅!《Apache Flink 十大技术难点实战》发布,帮你从容应对生产环境中的技术难题
|
消息中间件 运维 前端开发
做一个优秀的开源项目,需要注意哪些方面?
如果你想发布一个开源库,请确保它有以下特点: 清晰的依赖性和安装说明 至少有一个简要的文档指南 修改日志和仓库中的标签 关于支持的语言、运行时、工具版本的信息和项目的成熟度 一个可以让用户提问和交流的邮件列表 缺少任何一项都会造成一些用户的愤怒和沮丧,当然同时也浪费了时间。
365 0
|
SQL 消息中间件 存储
专治数仓疑难杂症!美团点评 Flink 实时数仓应用经验分享
实时处理技术,是强调当前处理状态的一门技术,所以我们认为这两个相对对立的方案重叠在一起的时候,它注定不是用来解决一个比较广泛问题的一种方案。于是,我们把实时数仓建设的目的定位为解决由于传统数据仓库数据时效性低解决不了的问题。
专治数仓疑难杂症!美团点评 Flink 实时数仓应用经验分享