后端面试题:外卖平台每天1000 万订单查询怎么优化?

AI 概述
一、先确认业务场景(别上来就堆方案)二、核心优化方案(按 “存储→缓存→检索→稳定性” 讲)1. 存储层:分库分表 + 双表隔离(解决单表 3 亿数据查不动)2. 缓存层:热点拦截 + 防坑三件套(解决查得慢)3. 检索层:ES 只存热数据(别让 MySQL 背锅)4. 稳定性层:限流 + 降级 + 监控(避免一崩全崩)三...
目录
文章目录隐藏
  1. 一、先确认业务场景(别上来就堆方案)
  2. 二、核心优化方案(按 “存储→缓存→检索→稳定性” 讲)
  3. 三、亮点与踩坑(显实战经验)
  4. 四、压测数据(用数据说话)
  5. 五、高频追问怎么答(都是我面过的题)
  6. 六、几个面试小技巧(亲测有用)
  7. 最后说两句

面试中被问到 “外卖平台每天 1000 万订单查询怎么优化”?这道题几乎是中大厂 Java 后端的 “必考题”—— 我去年面美团、饿了么时都遇到过,刚开始答得零散,后来总结出一套逻辑,两次都拿到了 “这个思路很清晰” 的评价。

今天把这套 “实战级答题框架” 整理出来,5 分钟能讲完核心方案,6 个高频追问也附了我当时的回答,都是落地过的真实经验,背熟直接冲 offer!

后端面试题:外卖平台每天 1000 万订单查询怎么优化?

一、先确认业务场景(别上来就堆方案)

我每次都会先问面试官几个问题,避免方案悬浮:

“您好,我先明确下核心约束:1000 万是日查询量吗?峰值 QPS 大概多少?主要是买家查近 30 天订单,还是商家要多条件对账?30 天热数据量大概有多少?”

(一般面试官会补充:日查询 1000 万,峰值 QPS 1000+,买家查单占 65%,商家筛选占 25%,30 天热数据 3 亿条)

二、核心优化方案(按 “存储→缓存→检索→稳定性” 讲)

这是我去年项目里落地过的四层架构,从 “查不动” 到 “稳如老狗” 全靠它:

1. 存储层:分库分表 + 双表隔离(解决单表 3 亿数据查不动)

最开始我们只按 buyer_id 分 16 库,结果商家查订单要扫全 16 个库,响应从 500ms 飙到 8 秒 —— 后来改成 “双表设计” 才解决:

  • 买家表:按 buyer_id%16 分 16 库,再按 “buyer_id%8+年月” 分表(比如 buyer_order_0_202401),买家查单直接定位单库单表;
  • 商家表:按 merchant_id%16 分 16 库,同规则分表,专门承接商家查询;
  • 为啥选 16 库?因为是 2 的幂次,后续扩到 32 库时,只需要迁移一半数据(要是 10 库扩 20 库,几乎要迁全量)。

2. 缓存层:热点拦截 + 防坑三件套(解决查得慢)

订单查询 65% 是买家查 “最近 10 条”,这部分必须用 Redis 拦下来:

  • 缓存 Key 设计:买家最近订单用order:buyer:recent:{id},TTL 设 1 小时,还加了 5 分钟内的随机偏移(比如 355 秒、362 秒),避免全量过期雪崩;
  • 商家当日统计用order:merchant:stat:{id},每 5 分钟定时刷新,不用实时查库。

我踩过三个坑,现在都会重点提:

  • 穿透:用布隆过滤器预加载活跃用户 ID,无效 ID 直接拦截,还加了 5 分钟空值缓存;
  • 击穿:有次大 V 用户缓存过期,瞬间 1000 + 并发打穿 DB,后来加了 Redisson 分布式锁,持锁 10 秒,只让一个请求回源;
  • 雪崩:最开始没加随机 TTL,整点缓存集中失效,DB CPU 直接飙到 90%,加了偏移后再也没出现过。

3. 检索层:ES 只存热数据(别让 MySQL 背锅)

商家要查 “近 7 天金额> 100 + 已完成” 的订单,MySQL 做这种复杂筛选太费劲,我们用 ES 承接:

  • 只存 30 天热数据(3 亿条),分 30 个分片(单分片 1 亿内性能最好),副本数 1(平衡性能和成本);
  • 查询时用 filter 替代 must(不计算相关性得分,提速 30%),只返回 order_id、amount 这些必要字段,还限制最多查前 100 页 —— 有次商家查第 90 页超时,后来就加了限制,引导用时间范围缩小范围。
  • ES 挂了咋办?自动降级到 MySQL,不过会限制查询时间≤7 天,避免拖垮库。

4. 稳定性层:限流 + 降级 + 监控(避免一崩全崩)

高并发下总得留后手:

  • 限流:用Sentinel限制单用户 QPS,买家 50 次 / 分钟,商家 20 次 / 分钟,避免恶意刷接口;
  • 降级:Redis 集群故障时,直接查 MySQL 返回核心字段(比如只给订单号、金额,备注这些非核心字段不返回);MySQL 压力高时,历史订单查询直接提示 “请缩小时间范围”;
  • 监控:我会重点看三个指标 —— 缓存命中率低于 80% 告警(说明热点没拦住)、MySQL 慢查询超 10 条 / 分钟告警、ES P99 超 200ms 告警,去年双 11 就是靠监控提前发现 ES 压力,临时加了个分片。

三、亮点与踩坑(显实战经验)

讲完方案,我会主动提两个亮点和三个坑,面试官很吃这一套:

  • 亮点 1:双表设计彻底解决跨库扫描,商家查询性能提升 10 倍 +;
  • 亮点 2:数据分层(热数据 MySQL→温数据 ClickHouse→冷数据 HDFS),存储成本降了 60%,之前全存在 MySQL 里,年租金多花 200 万;
  • 坑 1:刚开始只按 buyer_id 分库,商家查单扫 16 个库,被运营投诉了才改;
  • 坑 2:缓存更新先更 DB 再删缓存,并发场景下出现过 “用户付了钱,订单还是待支付”,后来改成 “先删缓存→更 DB→200ms 后再删一次” 才好;
  • 坑 3:一开始想把 40 亿历史数据全存 ES,结果集群 OOM,后来只存 30 天热数据就好了。

四、压测数据(用数据说话)

光说不练假把式,我会带真实数据:

“去年项目落地后,线上数据很直观:买家查最近 10 条订单,P99 从 5.8 秒降到 60ms;商家多条件筛选,P99 从 9 秒降到 320ms;MySQL CPU 从 85% 降到 35%,缓存命中率稳定在 90%+。双 11 那天峰值 QPS 12 万,零超时、零故障,完全扛住了。”

五、高频追问怎么答(都是我面过的题)

1. 分库分表后怎么扩容?(美团面过)

我当时答的是 16 库扩 32 库的方案,分四步:

  • 先迁移数据:只迁 user_id%16≠user_id%32 的,大概 50% 数据量,比全量迁快太多;
  • 双写 7 天:新订单同时写老库和新库,避免丢数据;
  • 灰度切流:先切 5% 流量到新库,观察 3 天没毛病,再切 30%,最后全量,整个过程 14 天;
  • 每天对账:凌晨 3 点比对老库和新库数据,有差异的自动补偿 —— 有次迁完发现 100 多条订单漏了,靠对账补回来了。

2. 缓存和数据库不一致怎么办?(饿了么面过)

我们业务能接受秒级延迟,所以搞了三层保障:

  • 正常流程:先删缓存→更新 DB→200ms 后再删一次缓存,覆盖 99.9% 的场景;
  • 补偿:更新失败就记到补偿表,异步线程每 10 秒扫一次,最多重试 3 次;
  • 兜底:每天凌晨 3 点全量对账,发现不一致的主动刷新缓存 —— 去年有次 Redis 集群重启,缓存全清了,靠对账把数据补回来了。

面试官还追问 “为啥不先更 DB 再删缓存”,我就举了个例子:线程 A 更新 DB 到一半,线程 B 查到旧数据并回填缓存,之后 A 删缓存也没用了,缓存会一直脏。

3. ES 查询慢怎么优化?(字节面过)

我分了四个维度说,都是实际调优过的:

  • 索引:单分片控制在 1 亿内,3 亿数据分 30 片,副本数 1(之前开 2 个副本,性能降了 40%);
  • 查询:filter 替代 must,指定返回字段,限制分页深度;
  • 存储:只存 30 天热数据,历史数据走 ClickHouse;
  • 熔断:超 5 秒就降级,去年有次 ES 集群负载高,靠熔断没影响核心查询。

4. 主从延迟怎么解决?(阿里面过)

分场景处理:

  • 强一致场景(比如支付后立刻查订单):强制查主库,我们用了个 @Master 注解,加了注解就路由到主库;
  • 弱一致场景(比如查历史订单):查从库,允许 1-2 秒延迟,用户基本感知不到;
  • 前端也配合:刚下单成功后,前端先显示 “订单创建中”,3 秒后再查接口 —— 有次主从延迟 5 秒,用户刚下单查不到,投诉说 “付了钱没订单”,加了这个提示就好了。

5. 双写失败怎么保证一致?(京东面过)

我们用 RocketMQ 事务消息,比本地消息表省心:

  • 下单时先写买家表,成功后发事务消息;MQ 会回查本地事务状态,确认成功了才提交消息;
  • 消费者收到消息后写商家表,成功就 ACK,失败会自动重试 3 次;
  • 重试 3 次还失败的,进死信队列,每天早上有人专门处理 —— 去年有次 MQ 集群波动,100 多单没同步,靠死信队列补回来了。

为啥不用本地消息表?之前用过,要定时扫表,加重 DB 负担,后来全换成事务消息了。

6. 数据库还是扛不住怎么办?(拼多多面过)

最后还有三板斧:

  • 读写分离升级:主库从 1 台扩到 2 台(双主),从库从 3 台扩到 6 台,读能力直接翻倍;
  • 冷热分离再极致点:7 天内的热数据放 MySQL,8-30 天的温数据放 ClickHouse,用户查的时候无感切换;
  • 业务降级:去年双 11QPS 超预期 30%,我们临时把 “订单商品图片” 改成异步加载,DB 压力立减 15%—— 非核心功能先砍,保住核心查询再说。

六、几个面试小技巧(亲测有用)

分享几个我面了 10 多家公司总结的小细节,能拉好感:

  • 答题节奏别太快:确认场景时慢一点,显严谨;讲方案时正常语速,别漏细节;说亮点和坑时可以稍快,显熟练。我之前有次讲太快,面试官让我 “再捋捋分库分表的逻辑”,后来就刻意控制了;
  • 别光说技术,提提业务价值:比如 “商家查询快了后,客诉率降了 90%”“买家订单页留存提升 25%”,面试官喜欢听技术怎么帮业务;
  • 卡壳了别慌:我有次忘 “双写补偿” 的细节,就说 “这块我稍回忆下… 对了,我们当时记了个补偿表,异步重试 3 次”,面试官没追问;要是实在不会,就说 “这个点我没实战过,但我的理解是 XXX”,别瞎编;
  • 主动互动:讲完缓存层可以问 “您这边项目里缓存主要防哪些问题呀?”,拉着面试官聊,比自己单说好多了。

最后说两句

其实高并发优化不是 “堆多少技术”,而是 “哪个问题用哪个技术解决”—— 我去年刚开始准备时,总想着把 ShardingSphere、ES、Redis 全堆上去,后来才发现,先搞清楚业务场景,再针对性设计方案,比啥都重要。

以上关于后端面试题:外卖平台每天1000 万订单查询怎么优化?的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。

「点点赞赏,手留余香」

1

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » 后端面试题:外卖平台每天1000 万订单查询怎么优化?

发表回复