美团三面:8000万订单查不动,一定要分库分表吗?

0 阅读4分钟

文章首发地址

写在开头

有个兄弟去面美团,三面被面试官问得汗流浃背。 面试官没问那些虚的,直接甩了个业务场景:“美团外卖的订单量级你懂的。假如 t_order 表已经 8000 万行了,用户查‘我的订单’经常转圈圈,甚至偶尔超时,你怎么搞?

这兄弟也是个老实人,直接把背好的八股文搬了出来:“这量级必须分库分表啊,索引树太高了,拆开了才好使。”

面试官听完放下了笔,反问了一句:“分库分表那是‘伤筋动骨’的架构重构。如果我们工期只给一周,且不准引入分布式事务中间件,你能不能在单表架构下把这活儿干了?

他当时就懵了。其实,这题考的不是你会不会用 ShardingSphere,而是你有没有**“存储治理”“异构解耦”**的实战经验。

一、 别迷信“分库分表”,那是最后的保底

很多兄弟一听数据量大就想拆,但你真的考虑过分表后的痛苦吗?

  • 非分片键查询: 以前一个 SQL 搞定,分表后你按 order_id 拆,那按 shop_id 查怎么办?全库扫描?数据库直接 CPU 100%。

  • 分布式事务:@Transactional 失灵了,你是上 Seata 还是写 TCC 补偿?每一个都是 Bug 高发区。

  • 工期成本: 数据迁移、代码改写、回归测试,一个月能上线都算你手快。

图片

二、 核心方案:异构索引 + 蚕食式归档

别死磕 MySQL,把压力卸载到专业的组件上。

图片

1. 异构索引:ES 才是查询的“救命草”

不要让 MySQL 既负责高频写,又负责多维查。

  • Canal 实时同步: 监听 Binlog 实时把数据“同步”到 Elasticsearch(ES)。

图片

  • 读写解耦:

  • 历史/复杂搜索: 比如搜“半年前的奶茶订单”,直接路由到 ES。

  • C 端近期查询: 查最近 1 个月的订单,直接走 MySQL 热表,速度极快。

  • 防坑细节: Canal 可能会延迟。我们的策略是:下单后 5 分钟内的订单查询强制查 MySQL,5 分钟后的逻辑再去查 ES。 这样用户感知不到同步延迟。

图片

2. 蚕食式归档:优雅地剔除“僵尸数据”

大表查询慢,很大程度是因为冷数据太多,把 B+ 树顶到了 4 层以上,且占满了 Buffer Pool。

图片

  • 不要直接 DELETE: 几千万行的 DELETE 会产生海量 Binlog,主从延迟能让你想哭。

  • pt-archiver 蚕食策略: 用 Percona 的 pt-archiver。这玩意儿好在哪?它能按行数小批量搬运。

图片

  • 方案细节: 每天凌晨,每秒只挪动 500 条数据到冷库/HBase。这种“蚕食”方式,主从无感,磁盘 IO 几乎没波动。热表始终控制在 500 万行的“轻量”状态,索引全在内存里。

三、 怎么保证数据不丢?(闭环思维)

面试官肯定会问一致性。你要拿出这种**“防御性编程”**的劲头:

  1. 状态位: 订单表加个 archive_status,归档成功后再改状态,最后清理。

  2. 离线核对: 每天凌晨跑个 Spark 任务,对比热库、冷库、ES 三方的数据 Count 值。

图片

  1. ACK 机制: 归档逻辑必须是“先入冷库,后删热库”,确保即便归档程序崩了,数据也还在原地。

四、 面试标准回答模板(直接拿去用)

“对于 8000 万规模的订单表,我倾向于**‘轻量化治理’**。

  1. 存储层面: 实施冷热分离。利用 pt-archiver 蚕食清理 3 个月前的非活跃订单,把热表规模压在 500 万行以内,保住 B+ 树的 3 层高度。

  2. 查询层面: 构建 Canal + ES 异构索引。将海量的历史搜索和复杂维度查询卸载到 ES 上。

  3. 稳定性: 引入离线核对机制做 ACK 闭环,确保三端数据最终一致。 这种方案不需要重构业务代码,不需要解决分布式事务,是性价比最高的打法。”

五、 Fox 的避坑口诀

大表查询别慌张,分库分表非良方。

先看冷热分没分,再看 ES 强不强。

pt-archiver 蚕食走,Canal 同步稳如羊。

架构解耦思维广,Offer 拿得才叫香!

写在最后

在大厂干活,最值钱的是**“对系统复杂度的控制力”**。能用异构索引和归档搞定的,绝对不要去动底层存储结构。永远保持核心数据库的“轻盈”与“纯粹”。

觉得有用的兄弟,点个赞,收藏起来,万一下次面试就用上了呢!

关注公众号【Fox爱分享】,只聊那些书上不写的实战坑。图片