Senior SWE · VO System Design

Uber Nearby Driver:动态位置的附近司机查询服务

根据 Uber VO 的 Proximity Service 面经,设计高频司机位置更新、按半径/数量查询附近可用司机、跨格边界、过期淘汰和真实路网距离复排。

题目重点:根据 Uber VO 的 Proximity Service 面经,设计高频司机位置更新、按半径/数量查询附近可用司机、跨格边界、过期淘汰和真实路网距离复排。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 写接口接收司机 ID、位置、状态、事件时间/版本;读接口给乘客位置、半径 r 和最大返回数 k,返回当前可接单且位置未过期的司机。
  • 题目未明确固定 r、k、在线司机数或位置 TTL;设计先把这些作为容量输入,而不编造 Uber 生产 SLA。
  • 默认用球面直线距离做候选距离,若业务要真实 ETA/路网距离,需调用路线服务对候选精排;路网距离至少不小于直线距离,但 ETA 不可由直线距离简单替代。

解题路线

  1. 按司机 ID 分区串行处理位置更新,维护最新版本的司机状态;位置改变时把司机从旧格索引移除、加入新格,并设置可续期的过期时间。
  2. 查询以乘客为中心找覆盖半径 r 的所有地理格作为候选,不只查同一格。格子编码可用 Geohash/H3/S2 等,分辨率需按城市密度和查询半径权衡;边界邻格必须覆盖。
  3. 合并候选 ID 后按最新状态和 TTL 最终过滤,再算精确直线距离与半径判断、排序/截断。若需路网最近,先用可证明不漏的候选覆盖,再对候选批量调用路由服务;不能无依据截掉全部直线距离较远者。
  4. 城市可作为粗分区,但跨城边界查询需读相邻分区。历史轨迹异步写入独立存储;当前查询路径优先保持低延迟。

手动走一遍

乘客在地理格边缘,司机在相邻格但直线仅 20 米。只查同格会漏掉司机;查询覆盖圆形半径的所有相交格,再对候选做精确距离过滤,才会返回该司机。若其最后更新已过期或状态为接单中,则排除。

规模与取舍

设查询覆盖 C 个格,候选总数 M,最终取 k。索引更新期望 O(1) 加存储一致性成本;查询扫描候选 O(C+M),按距离取前 k 用大小 k 堆 O(M log k),或排序 O(M log M)。热点格会使 M 很大,需更细分辨率/分片。

易错点与追问

容易失分的边界

  • Geohash 等编码的相同前缀不保证物理最近;半径可能覆盖超过 8 个邻格,要按真实范围计算覆盖集合。
  • 位置索引里留有过期或已接单司机会返回错误结果,必须用最新状态再核验。
  • 热力图的格子计数可以服务可视化,但不能直接提供司机 ID、精确半径、可接单状态和按路网 ETA 排序;两种读需求要分别建模。

继续深挖

  • 若司机每 4 秒更新,写入 QPS≈在线司机数/4;位置流先做版本去重/同格合并,再量化索引写、内存与网络压力。
  • 前端地图若不断跳动,可在展示层做位置插值/节流;派单候选仍应以服务端最新有效位置与状态为准。
✓已复制微信号!