中文 EN

系统设计 Lab

Ride matching 的瓶颈在于高频吞下司机 GPS、并快速回答 nearest-driver 查询,而不在请求量本身。

调节有多少司机在线、每个司机上报 GPS 的频率、ride-request 速率、搜索半径,以及服务多少个城市。设计会从单个 service 逐步演进到专门的 location-ingest 路径、用于 nearest-driver 查询的 in-memory geospatial index、durable 的 trip-state store,以及按 geo 分片加 surge pricing。

分步讲解

一步一步把它想清楚

常规演进场景

从左到右点击,就是预设的演示路径。每张卡片都会改变 workload 输入。

Workload

这些是输入,不是预设好的架构阶段。

推荐形态

当前架构路径
Ride-sharing matching 架构图 Ride matching 的白板风格架构图:司机和乘客、location-ingest 路径与 API gateway、带 matching service 的 in-memory geospatial index、durable 的 trip-state store,以及异步的 pricing 与 analytics pipeline。 Clients Ingest / gateway Geo + matching Trip state Pricing / analytics 司机 app GPS stream 乘客 app 发起叫车 API gateway 乘客请求 Location ingest 高写入速率 Geo index in-memory cell Matching service 配对 + 状态 Trip-state store state machine Geo shards 按城市 / cell Surge engine demand / supply Event stream 异步事件
Clients
司机 app 在线时每隔几秒上报一次自己的位置
乘客 app 请求和最近的可用司机进行 match
Ingest / gateway
API gateway 给乘客做鉴权,并把 match 请求路由到 matching service
Location ingest 吸收司机 GPS 更新的 firehose,并喂给 geo index
Geo + matching
Geo index 把司机的实时位置保存在 geohash/quadtree/S2 cell 里,用于 nearest 查询
Matching service 查 index 拿候选,把乘客和司机配对起来
Trip state
Trip-state store 持久化追踪每段行程,从 requested 到 matched 到 en route 再到 complete
Geo shards 按地理把司机和行程分片,让每个 region 独立扩展
Pricing / analytics
Surge engine 在 matching 热路径之外,按区域计算 surge 倍率
Event stream 收集行程和位置事件,供离线的 analytics 与 ML 使用

瓶颈

Location 写入吞吐

Geo-query 负载

Geo-index 内存

Matching + trip-state QPS

跨城市 / shard 压力

为什么会变

    决策权衡

    Location ingest 路径

    Geospatial index

    Matching service

    Trip-state store

    Surge pricing engine

    按城市 / geo 分片

    有出处支撑的规则

    这些是模型背后那些经得起时间考验的 system design 论断。而 slider 的具体阈值,则被刻意标注为教学用的假设。

    已验证的规则

    Uber 用 S2 geospatial cell 把乘客匹配给司机

    Uber 用层级化的 cell(H3,构建在 Google S2 之上)给整个世界建 index,让 nearest-driver 查找变成只扫一小撮 cell 的有界 scan。

    Uber Engineering
    已验证的规则

    Geohashing 把临近搜索变成 prefix range scan

    把经纬度编码成 geohash,让邻近的点共享同一个 prefix,于是一次半径查询就变成对 in-memory sorted-set 的一小组 range 读取。

    Redis Docs
    已验证的规则

    高频 location ingest 是一个 write-heavy 的 streaming 问题

    持续涌入的逐司机 GPS 事件,最好用一个 partitioned log 来吸收,把 ingest 与 index 和下游 consumer 解耦开。

    Apache Kafka
    已验证的规则

    Quadtree 能高效回答 2D 的 nearest-neighbour 查询

    Quadtree 递归地划分空间,于是一次区域查询只访问和搜索区域有重叠的 cell,而不是每个点都看。

    Wikipedia

    教学用假设

    • Location ingest 的写入速率按「在线司机数 × GPS 上报频率」建模;真实系统会对更新做 batch 和 dedup。
    • 单节点的 ingest、geo-query 和 trip-state 预算是保守的教学数字,不是厂商上限。
    • Geo-query 代价随搜索半径和 cell 密度增长;in-memory index 的内存随在线司机数增长。