如何设计 Uber Eats:一次系统设计模拟面试
一次模拟面试的整理:设计一个类似 Uber Eats 的系统。核心需求、数据建模与 Geohash、数据库选型、服务拆分,以及从搜索到下单的用户流程。
English version: How to Design Uber Eats: A System Design Mock Interview
这篇是一次系统设计模拟面试的整理:设计一个类似 Uber Eats 的系统,讨论构建大规模外卖平台要考虑的技术问题。
核心需求
- 餐厅可以在系统里添加、更新和移除自己。
- 顾客可以浏览餐厅,按多种条件(距离、送达时间)搜索,并下单。
- 配送员收到新订单的通知。
非功能需求
- 可扩展性:支撑大量餐厅、顾客和订单。
- 可用性:系统高可用,运转平稳。
- 安全:用户数据和支付信息必须受保护。
- 延迟:搜索和查看餐厅的响应时间要尽量短。
数据建模
- 餐厅表:名称、地址、位置坐标、菜单项。
- 顾客表:姓名、地址、位置坐标。
- 菜单项表:名称、价格、图片地址。
- Geohash:把地球划分成网格的技术,用来优化按位置的搜索。
数据库选型
- 餐厅数据用关系型数据库加只读副本:数据量可控,读多写少。
- 顾客数据用分片的 NoSQL:用户基数大,需要水平扩展。
系统设计
- 一个统一的体验层,编排各端(iOS、Android、Web)之间的服务调用。
- 餐厅服务:管理餐厅数据的增删改。
- 图片服务:处理图片上传,存到 S3。
- 图片审核 API(可选):用机器学习审核上传的图片。
- 搜索服务(Elasticsearch):按位置和送达时间搜索餐厅。
- 缓存层:缓存高频访问的餐厅数据,缩短响应时间。
用户流程(简化)
- 顾客用位置、送达时间等条件搜索餐厅。
- 搜索服务根据 Geohash 和送达时间估算(等时线)从 Elasticsearch 取出餐厅。
- 顾客选中一家餐厅,从缓存(如有)或餐厅服务读取详情。
- 顾客下单,订单被路由给相应的配送员。
结论
这次讨论给出了 Uber Eats 这类复杂系统的高层设计,重点在于扩展性、可用性、安全和用户体验这几个维度都要顾到。