滴滴国际商旅面试 — 模拟面试对话脚本(项目 5 层追问)
候选人:吴来象 | 目标:滴滴国际商旅后端负责人 使用说明:面试官(刁钻、压迫、质疑、深挖)× 你(口语化、诚实、不卑不亢)。 练习方法:找个朋友念面试官部分,你脱稿回答;或自己交替朗读,录音回放。 核心原则:被质疑时不硬刚,被追问不会时诚实收,细节深挖时不夸大。
项目一:国际火车票 GDS(5 层追问 + 防御)
第 1 层:项目介绍
面试官:你简历上写的第一个项目是国际火车票 GDS,简单介绍一下这个项目,重点讲你做了什么。
我:好的。这个项目是携程启动国际化战略之后,要从 0 到 1 搭一个全球火车票的分销系统。简单说就是把中国、英国、法国、德国、意大利这些国家的铁路产品整合起来,对上给携程各业务端提供统一的预订、出票、退改签接口。
我当时是技术经理,主要负责三块:一是整体架构设计,包括统一产品模型的抽象和多机房合规部署;二是团队从 0 到 1 的组建;三是跟海外供应商的技术对接。
这个项目最难的地方是各国铁路系统差异特别大,车次、席别、退改签规则全不一样。我的核心做法是抽象了一套统一的铁路产品模型,向上提供标准化接口,向下用适配器模式对接各国供应商,把差异屏蔽在适配层。最后项目顺利上线,给携程火车票国际化打了个底。
第 2 层:技术细节深挖
面试官:你说的统一产品模型,这个听着挺虚的。我追问一下,假如某个国家的退改签规则根本没法映射到你的标准模型上,比如它不是简单的"能退/不能退",而是跟购买时间、车次类型、用户身份都相关的复合规则,你怎么处理?
我:这个问题很实际,我们当时确实遇到过。我的处理思路是——标准模型不试图穷举所有规则,而是定义一个"标准策略容器"加上"扩展属性"。
具体讲,标准层只定义最通用的几个字段:是否可退、是否可改、手续费比例、时间窗口。这些能覆盖 80% 的场景。剩下 20% 的复杂规则,我们留一个扩展字段,里面存这个国家特有的规则描述,格式是结构化的 JSON。标准层不解析它,只负责透传。
真正要用这个规则的时候,比如用户要退票,适配层会根据具体的国家路由到对应的规则引擎去算。这样既保证了上层的统一性,又不会因为强行统一而丢失业务细节。
我个人觉得,抽象的关键不是"消灭差异",而是"把差异封装在正确的地方"。强行 100% 统一一定会扭曲业务,但 80% 统一加 20% 扩展,是工程上最务实的平衡。
第 3 层:边界与压力测试
面试官:你这个方案听起来合理,但我有个担心。你说多机房部署满足各国数据出境合规,但火车票订单是跨国的——一个中国用户在欧洲买火车票,这个订单数据到底存哪?如果用户回国后要查这笔订单,是不是要跨国拉数据?这不就违反 GDPR 了吗?
我:这个问题问到点子上了,这是我们当时纠结了很久的一个点。
我们的设计原则是"用户归属地优先"。也就是说,订单数据跟着用户走,不跟着行程走。中国用户在欧洲买的火车票,订单数据存中国机房;欧洲用户在中国买的,存欧洲机房。
这样做有几个考虑:第一,符合数据主体归属地的合规逻辑,用户数据回所属合规区;第二,用户后续查订单、退改签,都是本地访问,不跨国,体验好;第三,供应商侧的票务数据是另一回事,那是供应商自己存的,我们只存订单。
但确实有个场景要处理——欧洲供应商要回传出票结果,这个回传数据里有欧洲用户的信息吗?如果有,就涉及数据从中国传回欧洲。我们的做法是,回传只传业务必需的票务信息,PII 数据脱敏或者不传,对账用订单号关联,不依赖用户身份信息。
这个权衡的核心是"最小必要原则"——跨境只传业务必需的非敏感数据,敏感数据本地闭环。这套思路携程后来公开的全球化架构里也提到了,他们叫"合规区"概念。
第 4 层:个人贡献剥离
面试官:你这个项目团队多少人?我直接问,统一产品模型这套架构,是你自己设计的,还是团队讨论出来的?你的具体贡献占多少?
我:我直接说。团队高峰期 20 多个人,但核心架构设计阶段是 5 到 6 个人的核心组。
统一产品模型这套架构,主设计是我。我画了第一版架构图,定义了三层模型的标准字段。但我要诚实讲,不是所有细节都是我一个人想的——比如退改签策略容器的扩展字段设计,是当时一个资深同学在 review 的时候提的,他觉得纯标准字段兜不住,建议加扩展,我采纳了。
我的贡献主要是:架构的整体方向和分层是我定的;适配器模式的抽象是我设计的;跨国供应商对接的规范是我主导的;团队组建和跨团队协作是我负责的。具体到某一行代码,很多是团队写的,我不抢这个功。
我觉得技术负责人的价值不在写多少代码,在架构方向对不对、能不能把团队带起来。这个项目方向是我定的,出了问题我扛,这是我的贡献定位。
第 5 层:反思与迁移
面试官:好。最后一个问题,如果让你重新做一遍这个项目,你会改什么?另外,这套东西搬到滴滴国际商旅的机票 GDS/NDC 上,你觉得最大的风险在哪?
我:先说重做会改什么。
第一,我会更早引入全链路可观测。当时我们上线初期对供应商接口的监控比较粗,出问题定位慢。后来补了 TraceId 和细化指标,但有点晚,前期踩了坑。
第二,统一产品模型我会更激进地做版本化。模型演进的时候,因为没有版本控制,出现过上下游不兼容的情况。后来携程国际机票那边做中台化的时候用了数据版本控制,我觉得这个思路我当时应该想到。
第三,团队组建我会更早招一个懂国际合规的人,不只是技术,是懂 GDPR、懂数据出境法务的人。当时这块是边做边学,效率低。
搬到滴滴商旅机票 GDS/NDC 的最大风险,我认为有两点。第一是协议层——机票的 GDS 报文、NDC 标准、PNR 管理,这些我团队没做过,需要 1 到 2 个月通过供应商技术支持补齐,这段是有阵痛期的。第二是运价时效性——机票运价变化比火车票快得多,ATPCO 那边两亿条运价实时更新,缓存策略要重新设计,不能照搬火车票的。但架构方法论——统一模型加适配器加多机房合规——这个是通用的,我有信心。
项目二:千万级订单重构(5 层追问)
第 1 层:项目介绍
面试官:你简历说订单系统从 100 万提到 1000 万,这个数据是怎么统计的?是订单创建量还是支付量?先讲清楚。
我:这个数据我得说清楚口径,免得误导。100 万到 1000 万指的是日均订单创建量峰值,也就是用户下单的峰值,不是支付量。支付量会比这个低,因为有取消、有未支付超时的。
统计方式是订单主服务落的订单号计数,按天聚合,取的是春运那种峰值日的数据。100 万是重构前的峰值,1000 万+是重构后能扛的峰值,实际业务后来也跑到这个量级了。
这个数据是真实的,但我要诚实讲,1000 万不是每天都这样,是峰值。日常可能几百万,春运、节假日冲到 1000 万+。
第 2 层:技术深挖
面试官:你说按订单号 hash 分 8 库。我问个具体的,订单号怎么生成的?Snowflake 还是号段?如果是 Snowflake,跨机房时钟回拨怎么处理?如果是 hash 分片,订单号里嵌了分片位,那订单号生成本身就依赖分片信息,这不是循环依赖吗?
我:好问题,我拆开答。
订单号生成我们用的是号段模式,不是 Snowflake。原因是 Snowflake 依赖机器时钟,跨机房时钟回拨确实是个隐患,号段模式更可控。
具体讲,我们有一个独立的 ID 发号服务,预先从 DB 拿一个号段,比如 1 到 10000,缓存在内存里发,发完再拿下一段。订单号的格式里,末两位是分片位,这个分片位是发号的时候根据当前库的负载情况分配的。
关于循环依赖的问题——确实,订单号里嵌分片位,意味着发号要知道往哪个库分。我们的做法是发号服务和分片路由是同一个服务里做的,不是两个独立服务。发号的时候,先根据负载选一个目标库,再生成带这个库分片位的订单号。这样不是循环依赖,而是把发号和路由做成了一个原子操作。
这个设计有个前提,就是发号服务本身要高可用。我们做了发号服务的主备加多实例,每个实例负责一部分号段空间,互不冲突。
第 3 层:极端情况
面试官:你这个分库分表方案,如果某个库挂了怎么办?8 个库里挂 1 个,你那 1/8 的订单是不是就完全不可用了?你怎么保证这个场景下的可用性?
我:这是个很现实的问题,分库分表最大的痛点就是单库故障。
我们的做法是每个分库都做主从,一主一从或者一主多从,主挂了从能顶上。这是第一层。
第二层,如果是整个机房挂了,我们有异地灾备,数据是异步同步过去的。但这里要承认,异步同步会有数据延迟,灾备切换的时候可能丢最后几秒的数据。这部分我们通过消息队列的重放来补偿,业务侧做幂等兜底。
第三层,如果真到了某个分库完全不可用、从库也没顶上的极端情况,我们会做降级——这个分片的写请求先拒绝,引导用户稍后重试;读请求返回缓存数据或者提示异常。这 1/8 的用户确实会受影响,但不会拖垮整个系统。
我承认分库分表在单库故障上是有妥协的,没有完美方案。核心思路是"控制爆炸半径",一个库挂了影响 1/8,而不是全盘崩溃。这个权衡我觉得是值得的。
第 4 层:质疑与反驳
面试官:你提到 99.99% 可用性。我直接质疑一下,99.99% 意味着一年宕机不超过 52 分钟。你们真的做到了吗?有没有监控数据支撑?最近一次比较严重的故障是什么?怎么处理的?
我:我理解这个质疑,99.99% 这个数字确实容易让人怀疑。
先说怎么统计的。我们有独立的可用性监控,按分钟粒度采样核心接口的成功率,可用性 = 成功请求数 / 总请求数。这个数据是 SRE 团队统计的,不是我团队自己报的,相对客观。
99.99% 是年度数据,不是每个月都达标。我们有过几次小故障,但都在几分钟内恢复,年度摊下来确实在这个量级。我承认这个数字有"年度平滑"的成分,不能说每一秒都达标。
印象比较深的一次故障,是有一次数据库主从切换的时候,从库有一个长事务没追平,导致切换后部分请求读到旧数据,持续了大概 5 分钟。我们发现后立即回滚到旧主库,然后排查从库延迟原因,是那个长事务锁表导致 binlog 应用慢。事后我们加了主从延迟的实时监控和告警,切换前强制校验延迟阈值,这个问题后来没再出现。
所以我说 99.99% 是真的,但不是没故障,是故障够小够快恢复。稳定性这块我承认是个持续工程,不是一劳永逸的。
第 5 层:迁移到滴滴
面试官:滴滴商旅的订单比火车票复杂,有企业账户、有差标管控、有公对公结算、还有机加酒加车的组合订单。你这个订单系统搬过来,能直接用吗?哪些要改?
我:说实话不能直接用,但核心骨架能复用,差异在业务层。
能复用的是底层三件套——分库分表、状态机解耦、异步消息队列。这套骨架是通用的,跟业务无关。分片键可能要调整,商旅是 B2B,企业大客户的订单量更大,分片键要重新评估,可能不能单纯按订单号分片,要考虑企业维度,避免大客户订单热点。
要改的主要是业务层。第一是组合订单,机加酒加车要做主订单加子订单的双层状态机加 Saga 编排,这个火车票没有,要新设计。第二是差标管控,下单前要过差旅政策规则引擎,超标要审批,这个是商旅特有的。第三是结算,火车票是用户即时支付,商旅有公对公账期结算、有月结、有 VCC 虚拟信用卡,支付链路要重做。
所以我的判断是,底层技术骨架复用,业务层要基于商旅场景重新设计。这个工作量不小,但有了底层的底子,业务层迭代会快很多。这也是为什么我觉得我能胜任——底层的复杂交易系统我做过,业务层的学习曲线相对短。
项目三:TripPlan 跨境支付(5 层追问)
第 1 层:项目介绍
面试官:TripPlan 这个项目,你说用了大模型做行程规划。我问个直接的,这个项目真的上线了吗?有真实用户吗?还是个 demo?
我:我直接说,这个项目上线了,有真实用户,但规模不大,不是那种百万级用户的产品。它是面向入境游的定制游平台,用户量在千级到万级这个量级,是创业项目,不是大平台。
我说这个项目的价值不在规模,在于它完整落地了跨境支付和多币种定价的工程闭环。从 DDD 架构设计、到大模型和交易系统的解耦、到 Stripe 跨境支付对接、到 11 状态的订单状态机、到多币种定价引擎,这套是真实跑起来的,不是 PPT。
我承认规模跟携程不是一个量级,但工程复杂度是有的——跨境支付的坑、大模型的不确定性、多币种精度,这些难点不会因为规模小就消失。这个项目的价值在于验证了我能从 0 到 1 把一个复杂交易系统完整落地。
第 2 层:技术深挖
面试官:你说多币种用 BigDecimal,汇率从哪来?更新频率多少?汇率源挂了怎么办?用户下单时锁汇,那如果用户下单到支付之间汇率剧烈波动,锁定的汇率过期了怎么办?
我:逐个回答。
汇率来源我们接的是第三方汇率 API,当时用的是开放汇率接口。更新频率是每小时拉一次,缓存到本地。这个频率对定制游场景够用,因为客单价高、下单频次低,不像外汇交易那么敏感。
汇率源挂了的兜底,我们有两个:一是本地缓存的上一次汇率还能用,标记一下"非实时";二是设了阈值告警,汇率波动超过一定幅度或者长时间没更新,会触发人工介入。
锁汇过期的问题很关键。我们设了锁汇的有效期,比如 30 分钟。用户在 30 分钟内完成支付,按锁定汇率走;超时未支付,订单取消,重新下单要重新锁汇。这中间如果汇率剧烈波动,是平台承担还是用户承担?我们的策略是——锁定期间平台承担,因为这是我们给用户的承诺;超时后重新锁汇,按新汇率,用户承担。
这个设计其实跟携程商旅那个多币种结算专利的思路是一致的——固化汇率加预算池冻结。我们当时是先做的,后来看到携程那个专利,发现思路对上了。
第 3 层:边界与压力
面试官:你提到 Stripe 的 Webhook 幂等。我追问,Stripe 的 Webhook 可能乱序到达,比如退款成功的通知比支付成功的通知先到,你怎么处理?另外你说查询后置重试,如果查询接口本身也超时了呢?一直查一直超时,这笔订单永远悬着?
我:先说乱序问题。
Webhook 乱序是真实存在的,Stripe 不保证顺序。我们的处理是——不依赖 Webhook 的顺序,只依赖 Webhook 携带的事件类型和事件 ID。每个事件来了先看本地订单状态机当前在哪个状态,然后判断这个事件是不是合法的状态迁移。比如订单还在"待支付",来了一个"退款成功"事件,状态机校验不通过,这个事件不处理,但会记录下来,等"支付成功"事件到了之后再处理。
换句话说,状态机本身是乱序的天然防线。只要状态机定义严格,乱序事件会被挡掉或者缓冲。
再说查询后置重试一直超时的问题。这个确实是极端情况。我们的策略是分层兜底:第一次查询超时,间隔 30 秒重试;第二次超时,间隔 2 分钟重试;第三次还超时,进入人工对账队列,不再自动重试。订单状态标记为"不确定",人工通过 Stripe 后台或者其他渠道确认。
我承认这个极端情况下用户等待体验不好,但跨境支付宁可慢也不能错。一直悬着的订单占比极低,我们有 T+1 对账兜底,最终一定能平。这个权衡我觉得是对的——资金安全优先于体验。
第 4 层:个人贡献
面试官:这个项目你是技术合伙人,团队多少人?架构是你设计的,那大模型的部分谁做的?Stripe 对接谁做的?你是全栈一个人扛,还是团队分工?
我:团队不大,核心研发 3 到 4 个人。我是技术合伙人,整体架构是我设计的,包括 DDD 模块拆分、订单状态机、多币种定价引擎。
具体分工上,大模型的部分——需求收集模块、行程引擎模块——是我跟一个算法同学一起做的,我负责工程化封装,他负责 prompt 调优和模型选型。Stripe 对接和支付适配层是我自己写的,因为支付这块对安全性要求高,我亲自上手。
数据模型、约束校验、订单状态机这些核心模块是我设计的,部分代码是团队写的。MVP 阶段我写的代码不少,大概占 40% 左右,后面迭代主要 review。
我承认这个项目不是大团队作战,但我认为这反而证明了我的全栈能力——从架构到核心代码到支付对接,我能一个人扛下来。在大平台带 20 人团队是一回事,在创业期 3 到 4 人把复杂系统跑起来是另一回事,这两个能力我都有。
第 5 层:迁移与反思
面试官:商旅的跨境支付比定制游复杂多了,有企业账户、有账期、有发票、有 VCC。你这个 Stripe 对接经验,能 cover 商旅的支付场景吗?
我:我直接说,定制游的支付确实比商旅简单,但底层支付工程的能力是通的。
商旅多出来的部分,我梳理过:第一是企业账户和公对公结算,有 Central Billing、Local Billing、账期月结,这个定制游没有;第二是 VCC 虚拟信用卡,这个是商旅特有的;第三是发票,增值税专票、电子发票归集;第四是差标管控和预算池。
这些我承认没亲自主导过,但我有两个支撑:第一,我研究过携程商旅的多币种结算专利,固化汇率加预算池冻结加混付那套,原理我懂;第二,支付适配层的架构思路是通用的——不管对接 Stripe 还是 Adyen 还是 VCC,本质都是通道适配加幂等加对账,这套我在 TripPlan 验证过。
我判断,商旅支付的复杂度主要在业务规则层,不在支付工程层。业务规则我需要时间补,但工程架构我能扛。我不会夸大说我能立刻上手商旅全部支付场景,但给我一个季度的过渡期,我能带团队把这套搭起来。
项目四:全自动出票系统(5 层追问)
第 1 层:项目介绍
面试官:全自动出票系统,你说做了多引擎互保。火车票出票不就是调 12306 吗?为什么要多引擎?这个"多引擎"具体是什么?
我:我解释一下。火车票出票确实主要靠 12306,但 12306 不是只有官方接口一种途径。我们当时的多引擎指的是多种出票路径互为备份。
具体讲,一个引擎是官方接口,稳定性最好但有时候限流;第二个是模拟官网操作,也就是爬虫服务,通过模拟浏览器行为走官网流程出票,作为官方接口的补充;第三个是调度服务,负责协调前两个,根据健康状态和负载分配任务。
为什么要这么做?因为春运这种高峰期,12306 官方接口经常扛不住,单一路径出票成功率会掉。多引擎互保的好处是,官方接口限流了,爬虫服务还能顶上,整体出票能力不至于断崖式下降。
这个"多引擎冗余加调度协调"的思路,我觉得对机票出票也适用——机票有 GDS 报文层、有 NDC 直连,同样可以多通道互备。
第 2 层:技术深挖
面试官:你说爬虫服务模拟 12306 官网操作。12306 的反爬是出了名的强,你怎么抗反爬?验证码怎么过?被封 IP 怎么办?
我:这块我讲实在的。12306 的反爬确实强,我们的应对是几个层面。
第一是 IP 池,我们维护了大量代理 IP,做 IP 轮换,避免单 IP 高频请求被封。第二是请求频率控制,模拟正常用户的操作节奏,不暴力刷。第三是验证码识别,这块当时接了第三方打码平台,结合自研的图像识别,识别率能做到可用。第四是行为模拟,请求头、操作间隔、鼠标轨迹这些尽量贴近真人。
被封 IP 的情况肯定有,我们的策略是 IP 池定期更新,被拉黑的 IP 自动剔除,补充新 IP。同时调度服务会根据各 IP 的健康状态——成功率、响应时间——动态分配任务,不健康的 IP 降权。
我要诚实讲,这块是个持续的攻防战,12306 升级反爬策略,我们就要跟着调整。不是一劳永逸的方案,是个持续运营的事情。这个经验让我深刻理解了"外部依赖不可控"这件事,后来我做所有依赖外部系统的设计,都会预留降级和兜底。
第 3 层:边界与质疑
面试官:我直接质疑一下。你用爬虫模拟官网操作,这个合规吗?12306 没有封你们吗?这个方案放在滴滴商旅,机票的 GDS 可不是你能爬的,GDS 是有协议的。你觉得这个经验能迁移吗?
我:这个质疑很合理,我直接回应。
首先,火车票爬虫这个事情,在当时的行业环境下是个灰色地带。我们模拟的是正常用户的官网操作流程,没有攻击性,但确实不是官方授权的接口。这块我承认有合规风险,也是为什么行业里大家做但不太公开讲。
放到滴滴商旅的机票场景,我不能爬 GDS,这个你说得对。GDS 是有协议的,要走正规的 API 对接。但我想强调的是,这个经验里可迁移的不是"爬虫"本身,而是"多通道冗余加调度协调加监控归因"这套治理框架。
机票场景里,多通道指的是 GDS 报文层、NDC 直连、可能还有航司直连,这些是正规通道。但通道多了之后,怎么协调、怎么互备、怎么监控成功率、怎么归因失败,这套治理思路跟火车票多引擎是一样的。火车票我解决的是"官方接口扛不住怎么办",机票要解决的是"GDS 慢或者出票失败怎么兜底",问题结构是一样的。
所以我的判断是,爬虫这个具体手段不能迁移,但多通道治理的工程能力可以迁移。我不会在滴滴去爬 GDS,但我会用同样的思路做 GDS 加 NDC 的多通道出票治理。
第 4 层:数据追问
面试官:你说出票成功率和稳定性行业领先,具体多少?怎么统计的?跟行业比领先多少?这个"数百万运营成本"怎么算出来的?
我:我说具体的。出票成功率峰值能做到 99% 以上,日常 98% 左右。这个统计是出票服务落的成功数除以总尝试数,按分钟粒度统计。
跟行业比,当时同行的出票成功率大概在 95% 到 97% 这个区间,我们高 1 到 2 个百分点。听着不多,但在春运那种亿级订单的场景下,1 个百分点就是几十万张票,影响很大。
"数百万运营成本"这个是这样算的——如果没有自动出票,高峰期要靠人工出票,人工成本加上错票退改的赔付成本,一年算下来大几百万。自动出票上线后,人工干预率降到很低,这部分成本省下来了。这个数据是运营团队算的,不是我技术团队报的。
我承认"行业领先"这个说法有点主观,但成功率数据是客观的。我也不能说我们绝对第一,但在头部玩家里我们是领先的,这个有底气。
第 5 层:迁移与反思
面试官:如果机票出票成功率只有 92%,你怎么治理?前 3 个月你会做哪几件事?
我:92% 偏低,正常应该在 96% 以上。我会按"归因加分级加治理"三步走。
第一个月,做失败归因分析。把出票失败的 case 全部分类——是 GDS 报文错误、是 NDC 接口超时、是库存被抢、是用户信息不全、还是支付超时。归因清楚了才知道往哪使劲。我做过火车票的失败归因大盘,这套方法论能直接搬。
第二个月,根据归因做分级治理。比如 GDS 报文错误占 30%,那就针对报文层做容错和重试策略;库存被抢占 20%,那就优化占位加锁的逻辑;支付超时占 15%,那就优化支付链路。同时建出票成功率的大盘和告警,实时监控。
第三个月,做多通道互备。GDS 主通道加 NDC 直连备通道,任何一个通道出问题自动切换。再加上出票后的对账,确保票务状态一致。
我对出票治理这套有信心,因为火车票出票的难度不亚于机票——12306 的反爬和限流比 GDS 难搞多了。我能把火车票出票做到 99%,机票治理的思路是一样的,只是协议层要补。
项目五:抢票系统(5 层追问)
第 1 层:项目介绍
面试官:抢票系统拿 CEO 大奖,这个奖含金量挺高的。讲讲这个系统,重点说你个人的贡献,为什么能拿奖。
我:抢票是火车票业务的核心战役,春运抢票直接决定市场占有率。我当时独立负责抢票票台,就是负责抢票这一整套技术。
系统的核心是三个设计。第一是任务分级,按用户优先级和车次热度分级调度。第二是多引擎并发,多个出票引擎同时抢,哪个先成功用哪个。第三是最有技术含量的——余票预测加任务合并,预测余票什么时候释放,在释放时点集中火力,同时把同车次多用户的抢票任务合并,减少无效请求。
为什么能拿 CEO 大奖,我认为核心是市场占有率做到了第一,而抢票能力是市场占有率的关键。技术上,余票预测加任务合并这个设计,能大幅提升抢票命中率,同时降低对 12306 的无效请求压力,是当时行业里做得比较领先的方案。
我个人贡献是,整个抢票票台的架构是我设计的,余票预测算法和任务合并逻辑也是我主导的。这个项目是我独立负责,团队配合我执行。
第 2 层:技术深挖
面试官:余票预测怎么做的?12306 又不会告诉你它什么时候放票。你预测的依据是什么?预测准确率多少?
我:我讲实在的,余票预测不是预测 12306 内部的放票时刻,那个谁也预测不了。我们预测的是基于历史规律的余票释放模式。
具体讲,12306 的余票释放是有规律的。比如某些车次会在固定时间点释放一批退票,或者开车前一段时间释放一部分未售仓位。我们积累了大量历史数据,统计出不同车次、不同时段的余票波动规律,用这个规律预测未来一小段时间内余票可能释放的窗口。
预测准确率这个我要诚实讲,没法给一个精确数字,因为它不是二元的"准/不准"。我们的做法是预测一个"高概率释放窗口",在这个窗口内集中抢票,命中率比随机抢高 30% 到 50%。这个提升是统计意义上的,不是每次都准。
另外任务合并也很关键。同一个车次有 100 个用户在抢,我们不是发 100 次请求,而是合并成少数几个请求,一旦抢到再内部分配。这样对 12306 的压力小,命中率反而高,因为请求少了不容易被限流。
第 3 层:质疑与边界
面试官:我直接质疑。抢票这个业务,本质上是利用技术优势抢占公共资源,是不是有点"黄牛"性质?而且你说的任务合并,100 个用户抢 1 个余票,抢到了分给谁?这不公平吧?另外,这个经验对商旅有什么用?商旅又不抢票。
我:这几个问题我一个个回应,都是好问题。
先说黄牛性质。我理解这个顾虑,但抢票跟黄牛有本质区别。黄牛是囤票加价倒卖,抢票系统是帮真实用户在公平规则内提升抢票成功率,不囤票不加价。当时是携程这样的正规平台在提供服务,遵循 12306 的规则,不破坏规则。当然,从更高的角度看,抢票这件事反映的是铁路运力不足,技术只能缓解不能根治,这个我认同。
任务合并的公平性问题,这个我们设计过。合并的不是"100 个用户抢 1 张票",而是"100 个用户抢同一车次的不同席别"。一个车次有硬座、硬卧、软卧多种席别,我们合并的是同车次的请求,抢到之后再按用户优先级和席别偏好分配。如果一个车次只有 1 张票 100 个人抢,那就是按用户优先级——比如会员等级、下单时间——分配,这个规则是透明的,不是黑箱。
对商旅的迁移,我承认商旅不抢票,但抢票的底层能力可迁移。第一是"高频探测加任务合并",商旅旺季机票库存争抢是同构问题,十一热门航线就是抢库存。第二是"多引擎并发加调度",商旅多供应商并发询价也是这个模式。第三是高并发系统的设计经验,抢票是火车票里并发最高的场景,这个经验对商旅峰值场景有价值。
第 4 层:个人贡献
面试官:你说独立负责,团队多少人配合?余票预测算法是你自己写的还是算法同学写的?你说的"市场占有率第一",这个是抢票系统的功劳还是整个火车票业务的功劳?把功劳全归到抢票系统上,是不是有点夸大?
我:这几个点我澄清一下。
团队配合执行的有 4 到 5 个人,但架构设计和核心算法是我主导的。余票预测算法的初版是我写的,后面优化有一个数据同学帮我做模型调优,但算法框架和思路是我的。
"市场占有率第一"这个,我承认不是抢票系统单独的功劳,是整个火车票业务的功劳——产品、运营、技术、供应链一起的结果。但抢票能力是市场占有率的关键技术因素之一,因为春运这种场景,用户选平台第一看的就是抢票能不能抢到。抢票系统能力强,用户留存就高,这个是直接相关的。
我说"抢票系统获 CEO 大奖",不是说抢票系统单独把市场占有率做到第一,而是说抢票系统作为关键技术贡献,获得了集团年度大奖的认可。这个奖是评给项目的,我是项目负责人。我承认把功劳全归到抢票系统上是夸大,但抢票系统在其中的关键作用,这个我有底气。
第 5 层:反思
面试官:抢票系统你有没有做过什么错误决策?事后复盘觉得不该那么做的?
我:有一个。早期我们在余票预测上过于激进,预测到释放窗口就集中发大量请求,结果有一阵子被 12306 识别为异常流量,整个 IP 段被封了一段时间,反而导致抢票能力下降。
事后复盘,我们的问题是——光想着提升命中率,没控制好请求节奏,被反爬识别了。后来我们调整了策略,预测窗口内也控制请求频率,模拟正常用户分布,不做集中爆发。命中率略降了一点,但稳定性大幅提升,整体效果更好。
这个教训让我理解了一件事——技术优化不能只看单一指标,命中率不是越高越好,要跟稳定性平衡。被识别为异常流量这种事,一旦发生损失很大。这个思维后来我用到所有外部依赖的场景——控制节奏、模拟正常、预留缓冲,不追求极限值,追求可持续。
项目六:IoT 共享平台(5 层追问)
第 1 层:项目介绍
面试官:IoT 共享平台这个,你做的共享设备是什么设备?设备在线率 99.5% 这个数据,IoT 设备在线率能做到 99.5% 挺难的,怎么做到的?
我:具体设备我不展开讲,是面向 B 端场景的共享设备,跟共享充电宝、共享雨伞这类形态类似但不完全一样。
99.5% 的在线率,我要说清楚口径。这个是在线设备数除以注册设备数,按分钟采样。IoT 设备在线率确实难做,难点在于设备端的不稳定——网络抖动、断电、固件 bug 都会导致掉线。
我们做的几件事:第一是基于 Netty 自研了设备接入层,TCP 长连接加 Protobuf,保证连接通道稳定,有心跳保活和断线重连机制。第二是设备端有固件的 OTA 升级,修复已知的掉线 bug。第三是服务端有设备健康监控,掉线设备自动告警,运营介入。
我承认 99.5% 不是 99.99%,IoT 设备的物理特性决定了做不到那么高。但 99.5% 在共享设备这个场景已经是可用水平,能支撑业务运转。
第 2 层:技术深挖
面试官:Netty 自研接入层,为什么不用现成的 MQTT broker 比如 EMQX?自研的理由是什么?自研的代价你评估过吗?
我:这个选择当时确实纠结过。用现成的 MQTT broker 优点是快,开箱即用;缺点是我们的协议不是标准 MQTT,设备端固件已经定型,改造成本高,而且我们的业务场景有些特殊,比如支付分账触发设备指令,跟标准 MQTT 的 pub/sub 模型不完全契合。
自研的理由主要是协议兼容和定制化。我们用 Protobuf 做序列化,设备端改动小;接入层跟业务层紧耦合,支付触发指令这种场景能直接做。自研的代价我也评估过——主要是运维成本和稳定性风险,没有 EMQX 那种成熟社区的兜底。
我的应对是,接入层做得足够简单,只做连接管理、心跳、协议解析,不做复杂业务逻辑,复杂逻辑下沉到业务层。这样接入层的稳定性可控,出问题的面比较小。
说实话,如果是今天重新选,我会更倾向用 EMQX 然后做适配层,减少自研负担。当时自研有当时的考虑,但我也承认这不是最优解,是个权衡。
第 3 层:支付分账
面试官:你说支付分账月流水 100 万+,分账是怎么做的?分给谁?分账的合规性怎么保证?设备收益分账跟商旅支付是两回事,这个经验能迁移吗?
我:分账场景是这样的,共享设备的收益要在平台、设备投放方、物业方之间分。用户扫码支付后,资金按约定比例实时或者 T+1 分到各方账户。
技术上,分账系统对接了第三方支付的分账接口,比如微信支付的分账能力。每笔支付成功后,触发分账指令,按配置的比例分配。分账比例是可配置的,不同设备、不同场所有不同的分账规则。
合规性这块,分账要走持牌支付机构的通道,资金不过平台账户,直接从用户到各方,避免二清风险。这个我们当时对接的是有牌照的支付机构。
迁移到商旅的话,分账本身跟商旅支付不是一回事,但支付工程的底层能力是通的——支付订单管理、幂等、对账、退款这套,跟商旅的支付链路是一样的。分账的复杂度在多方资金分配,商旅支付的复杂度在跨境多币种和企业结算,难点不同但工程框架类似。我不会说分账经验直接迁移到商旅,但支付工程的底子是有的。
第 4 层:个人贡献
面试官:IoT 平台团队只有 3 个人,你带了 3 个人做了一套 IoT 平台加支付分账。这个听着有点夸张,3 个人能做这么多?哪些是你做的,哪些是外包?
我:我直接说,3 个人是核心研发团队,不是全部。设计、测试、运维有其他支持,但核心代码是 3 个研发写的,没有外包。
我自己写的是接入层架构、支付分账系统、还有核心的数据模型。另外两个同学一个负责设备端 SDK 和业务逻辑,一个负责管理后台和运营系统。
3 个人能做这么多,有几个原因:第一是创业期节奏快,没有大公司那种流程损耗;第二是技术选型上用了很多成熟框架,Spring Boot 加 Redis 加 MySQL 这套,不重复造轮子;第三是我作为技术合伙人写了不少核心代码,不是纯管理。
我承认这个团队规模在大平台看不大,但创业期就是要在资源有限的情况下把事做成。这个经历锻炼了我"少人办大事"的能力,也证明了我能从架构到代码全栈落地。在大平台带 20 人团队和创业期带 3 人团队,能力维度不一样,我两个都有。
第 5 层:迁移与反思
面试官:IoT 平台和商旅业务差挺远的。你觉得这段经历对你做滴滴商旅有什么实际帮助?不要讲虚的。
我:我不讲虚的,说实际的。
第一,0 到 1 的全链路能力。从需求到架构到代码到上线到运营,IoT 平台是我完整跑了一遍的。商旅也是 0 到 1,这套全链路的节奏感能直接用。
第二,支付工程的底子。支付分账虽然跟商旅支付不同,但支付订单管理、幂等、对账、退款这套工程实践,我做了一遍,商旅支付能复用骨架。
第三,资源有限下的优先级取舍。3 个人做平台,必须砍掉非核心的,集中力量做关键路径。商旅 0 到 1 也是资源紧张的,这种取舍能力有用。
我不夸大 IoT 跟商旅的直接关联,业务确实差得远。但工程能力、0 到 1 的节奏、资源约束下的决策,这些是可迁移的。这也是为什么我觉得我的多元化经历是优势而不是散——每段经历锻炼的能力维度不同,拼起来恰好覆盖商旅负责人的能力图谱。
项目七:AI 智能客服(5 层追问)
第 1 层:项目介绍
面试官:AI 智能客服系统,你做了规则引擎加大模型双层意图路由。这个"双层"具体怎么分的?为什么不直接全用大模型?
我:双层是这么分的。第一层是规则引擎,处理高频、标准化的用户意图,比如查订单、退票、改签这些,规则明确、量大,用规则引擎快且准。第二层是大模型,处理规则引擎兜不住的复杂、长尾意图,比如用户描述很模糊或者多轮交互的场景。
不直接全用大模型的原因有三个。第一是成本,大模型每次调用都有费用,高频简单问题用大模型是浪费。第二是延迟,大模型响应慢,简单问题用户等不起。第三是准确性,规则引擎对标准化问题的准确率比大模型高,大模型有幻觉风险。
所以双层的设计是——规则引擎优先,命中率大概 70% 到 80%,剩下的走大模型兜底。这样兼顾成本、速度和覆盖率。
第 2 层:技术深挖
面试官:规则引擎和大模型之间怎么衔接?规则引擎没命中,转给大模型的过程中,用户感知到延迟吗?大模型的响应时间你怎么优化的?
我:衔接这块,规则引擎和大模型是串联的。用户请求进来先过规则引擎,规则引擎有一个置信度判断——如果命中规则且置信度高,直接返回;如果没命中或者置信度低,转给大模型。
用户感知延迟的问题是真实存在的。规则引擎处理是毫秒级,大模型是秒级,这个落差用户能感觉到。我们的优化是:第一,规则引擎没命中转大模型的时候,先给用户一个"正在为您查询"的过渡回复,掩盖延迟;第二,大模型用流式输出,第一个 token 出来就开始返回,不用等全部生成完;第三,大模型的结果做缓存,相似问题命中缓存直接返回。
另外规则引擎的命中率本身要持续优化,命中率高了,走大模型的比例就低,整体延迟就下来。我们定期分析未命中的 case,把高频的沉淀成新规则,不断提升规则引擎覆盖率。
第 3 层:限流熔断
面试官:你提到四级令牌桶限流和熔断保护。四级是怎么分的?大模型挂了怎么办?规则引擎挂了怎么办?
我:四级限流是按维度分的。第一级是网关层,按 IP 或者用户 ID 限流,防恶意刷。第二级是接口层,按接口维度限流,保护后端服务。第三级是服务层,按服务实例限流,防雪崩。第四级是大模型调用层,按 token 消耗限流,控成本也防大模型被打爆。
熔断保护主要在两个地方。一个是规则引擎到下游服务的调用,下游挂了熔断,返回降级提示。另一个是大模型调用,大模型响应慢或者报错率高了熔断,转人工客服兜底。
大模型挂了的情况,我们的策略是降级到人工——大模型不可用的时候,复杂意图的请求直接进人工队列,由人工客服处理。这个体验确实差,但保证服务可用。
规则引擎挂了的情况,规则引擎本身是高可用部署的,多实例加负载均衡。如果整个规则引擎集群挂了,所有请求走大模型兜底,大模型扛不住再降级人工。这是个逐级降级的链路,每一层挂了都有下一层兜底。
第 4 层:可观测性
面试官:你提到 OpenTelemetry 全链路 TraceId。客服系统的可观测性,你觉得最关键的指标是什么?你怎么定位一个"用户问题没被正确处理"的 case?
我:客服系统最关键的指标,我认为是首问解决率,也就是用户第一次提问就被正确处理的比例。这个指标直接反映系统有效性。其次是平均响应时间、人工转接率、用户满意度。
定位"用户问题没被正确处理"的 case,靠的是全链路 TraceId。每个用户请求有一个唯一 TraceId,从网关到规则引擎到大模型到下游服务,全链路透传。出了问题,拿 TraceId 在链路追踪系统里一查,能看到这个请求每一步的处理结果——规则引擎命中了哪条规则、置信度多少、大模型生成了什么、为什么最终回复是错的。
我们还会做 case 归因。每周抽一批未解决或者转人工的 case,人工 review,分析是规则缺失、是大模型幻觉、还是下游数据不对,然后针对性优化。这个闭环是客服系统持续提升的关键。
第 5 层:迁移
面试官:客服系统跟商旅后端关系不大吧?这段经历对商旅有什么用?
我:我直接说,客服系统跟商旅后端确实不是直接相关,但有两块能力可迁移。
第一是限流熔断和高可用设计。客服系统是个高并发、强依赖外部服务(大模型)的场景,限流熔断降级这套高可用设计是通用的。商旅系统同样需要多级限流、熔断、降级,这套设计能力能直接用。
第二是全链路可观测。TraceId 全链路追踪、case 归因闭环这套,商旅的故障定位和持续优化同样需要。商旅订单链路长,从搜索到下单到支付到出票,出问题要能快速定位,可观测性是关键。
我不夸大客服系统对商旅的直接价值,业务确实差得远。但高可用和可观测这两块工程能力,是后端负责人的通用能力,不分业务领域。这段经历补齐了我在 AI 和高可用可观测这块的能力,让我做商旅后端的时候,在系统稳定性上有更深的理解。
项目八:数据系统优化(5 层追问)
第 1 层:项目介绍
面试官:数据系统优化,3500 车站、3.6 亿站站组合。这个 3.6 亿怎么算出来的?是 3500 的平方吗?这个数据量级存哪?
我:3.6 亿是这么算的,3500 个车站两两组合,理论上是 3500 乘 3499,大概 1220 万。但实际站站组合不是任意两点都有直达,要考虑中转,加上不同车次、不同席别,实际的查询组合数会膨胀到 3.6 亿这个量级。这个数是业务方统计的实际可查询组合数。
存储上,不是把这 3.6 亿条全存 DB,那不现实。我们的做法是核心的站点关系和基础数据存 MySQL,热点查询结果缓存到 Redis,冷数据用 Elasticsearch 做索引。Redis 是大头,当时消耗很大,所以才有了后续的优化。
第 2 层:技术深挖
面试官:你说节省了 60% 的 Redis 资源,查询从秒级到毫秒级。60% 这个数怎么省的?主动加被动动态缓存策略具体是什么?
我:60% 是这么省的。优化前,我们的 Redis 用法比较粗——所有查询结果都缓存,TTL 统一设,导致大量冷数据占着内存。
优化后做了几件事。第一是分级缓存,把数据按热度分级——热点数据(比如北京到上海这种大站)放 Redis 且 TTL 长;温数据放 Redis 但 TTL 短;冷数据不缓存或者放 ES。这样 Redis 只存有价值的。
第二是主动预热加被动加载结合。热门线路主动预热,冷门线路用户查询的时候才加载进缓存,加载之后短 TTL 复用。这叫 passive caching,按需加载。
第三是缓存淘汰策略优化,用 Redis 的 LRU 加上业务感知的淘汰,优先淘汰冷数据。
60% 的节省主要是分级缓存贡献的,把不该缓存的数据踢出去,Redis 的有效利用率大幅提升。查询从秒级到毫秒级,主要是热点数据命中率高了,加上 ES 的冷数据查询也做了优化。
第 3 层:边界
面试官:3.6 亿组合,冷启动怎么办?Redis 全空的时候,第一批用户查询是不是都很慢?你怎么处理的?
我:冷启动确实是个问题。Redis 全空的时候,所有查询都打到底层数据源,响应慢。
我们的处理是预热机制。系统启动或者 Redis 故障恢复的时候,有一个预热任务,基于历史查询的热度数据,把 top N 的热门组合预先加载到 Redis。这个预热是分批的,优先加载最热的,保证大部分用户查询能命中。
冷启动期间,未命中的查询走降级——返回基础信息(比如有车次但无实时余票),提示用户"数据加载中",同时后台异步加载。等预热完成,恢复完整查询。
我承认冷启动期间体验有损,但通过预热和降级,能把影响控制在短时间和少数用户。这个经验对商旅也有用——商旅的运价数据、酒店静态数据量也大,冷启动和缓存预热同样要处理。
第 4 层:质疑
面试官:你这个优化,听着像是常规的缓存优化,没什么特别的。60% 的节省和毫秒级响应,是不是之前缓存策略太差,优化空间本来就大?这个项目的难度在哪?
我:我承认,这个优化本身不是什么突破性的技术,缓存分级、预热、按需加载这些都是常规手段。60% 的节省确实有一部分原因是之前策略粗,优化空间大。
但我想说明这个项目的真正难度在哪。第一是业务复杂度——3500 车站、3.6 亿组合,不是简单的 key-value 缓存,要考虑中转、车次、席别多维度,缓存 key 的设计和失效策略很复杂。第二是数据一致性——缓存的数据跟 12306 实时数据要尽量一致,余票变化要及时更新缓存,这个一致性保障是难点。第三是热点的动态变化——春运期间热点线路跟平时完全不同,缓存策略要能自适应。
所以这个项目的技术含量不在某个单点,在于把缓存策略跟业务特性深度结合。优化结果好,一部分是之前底子差,一部分是业务理解深。我不会说这个项目有多突破,但它是火车票数据系统的关键优化,对我理解大规模数据缓存有实在的锻炼。
第 5 层:迁移
面试官:机票运价数据比火车票复杂得多,ATPCO 两亿条运价实时更新。你这个缓存经验能迁移吗?运价时效性怎么处理?
我:我承认机票运价比火车票复杂,量级更大、更新更频繁、时效性要求更高。但缓存策略的思路是通的,差异在细节。
迁移的话,我会这么调整。第一,分级的标准不一样——机票要按航线热度、航司、舱位多维度分级,比火车票的站站组合维度更多。第二,TTL 策略更精细——运价变化快,热门航线 TTL 要短,甚至实时校验;冷门航线可以缓存长一点。第三,失效策略——ATPCO 推送运价变化的时候,要主动失效对应缓存,不能等 TTL 自然过期。
运价时效性这块,核心思路是"缓存负责快,实时校验负责准"。展示用缓存保证响应速度,成交前走实时验价保证准确。这个思路跟我前面讲的机票搜索优化是一致的。
我对大规模数据缓存有实战经验,机票运价虽然更复杂,但缓存工程的骨架是通的。需要补的是 ATPCO 的数据格式和推送机制,这个有供应商支持,能补上。
综合练习建议
怎么用这份脚本练
- 第一遍:通读,感受面试官的刁钻度和你的应对节奏。
- 第二遍:找朋友念面试官部分,你脱稿回答,录音。重点是练"被质疑时不慌、被追问不会时诚实收"。
- 第三遍:回放录音,对照脚本里的回答,找三个差距——结构化程度、数据支撑、诚实度。
- 重点练防御:每个项目的第 3、4 层是刁钻追问,重点练这些。被质疑数据真实性、被剥离个人贡献、被质疑合规性,这些是高压点。
三个最重要的应对原则
- 被质疑数据:先说清口径和统计方式,承认局限,不硬撑。比如"1000 万是峰值不是日均"。
- 被剥离贡献:明确区分"我设计的/我写的/团队写的/我了解的",不抢功也不推责。
- 被质疑迁移性:承认业务差异,讲清可迁移的是方法论不是具体实现,诚实说需要补的部分。
最该警惕的 3 个坑
- 夸大:被追问细节时,没做过的不要说做过,会被问穿。
- 硬刚:面试官质疑时不要对抗,先认可合理部分再补充。
- 含糊:数据要能说清口径,"大概""很多"会被追问到底。
这份脚本覆盖了你简历上所有 8 个项目,每个 5 层追问。练熟之后,面试官从任何项目切入、怎么深挖,你都有应对的底稿。关键是把"诚实但有说服力"这个分寸练出来——这是高级别面试的核心。