面灵AI→

京东后端实习一二面面经:Lua 脚本与订单超时关闭

轮次
一二面
结果
OC
时间
2026-09
来源
牛客网

《面试题目》

一面(技术面)

  1. 自我介绍。
  2. 实习中最有挑战的地方是什么?(会顺着你的回答深入追问)
  3. 你使用过哪些 AI 工具?
  4. Codex 和 Cursor 有什么区别?
  5. 使用 AI 工具的时候,你的开发流程是怎样的?
  6. 你会自己写开发流程吗?Agent 为什么会按照这个流程去做事情?
  7. 项目中印象最深的点是什么?
  8. 订单对账怎么做的?
  9. 订单 id 什么时候生成?
  10. 为什么使用 Lua 脚本?它有什么特点?
  11. 场景题:用户下了订单,超过十分钟没有支付,系统要自动关闭这个订单。让你来实现的话,你会用什么技术方案?
  12. Java 这块你是怎么学习的?什么时候开始学的?
  13. 反问环节:业务方向与团队里的 AI 实践。

二面(HR 面)

  1. 实习中最有挑战的地方是什么?你是如何去解决的?解决之后达到了什么样的效果?
  2. 项目中还有什么比较有挑战、或者让你有成就感的事情?
  3. 实习生如何培养?多久出结果?(反问)

《参考解析》

订单超时自动关闭:主流方案与取舍。这道题的关键是先说清楚”精度要求有多高”,再选方案:

  • 定时任务扫表:用一个调度每分钟扫一次 status=待支付 AND create_time < now-10min 的订单。实现最简单、天然幂等(重复扫到也不会重复关),缺点是精度只有分钟级、订单量大时全表扫描压力大(要靠状态加索引并分片)。中小规模业务首选。
  • 延迟消息:下单时往 RocketMQ 发一条延迟 10 分钟的消息,消费端收到后查一次订单状态,仍未支付就关闭。精度好、没有轮询,代价是依赖 MQ 的延迟消息能力,且消息可能丢失(要做补偿)。
  • Redis 过期 + 延迟队列:把订单号写进 ZSet,score 设为到期时间戳,另一个线程轮询 ZRANGEBYSCORE 捞到期订单。也可以用 key 过期事件,但 Redis 的过期通知不保证可靠投递(键被淘汰或实例重启就丢了),生产上一般只作辅助。
  • 时间轮:Netty 的 HashedWheelTimer 或 Kafka 的时间轮,适合单机内高精度定时,多实例下要配合分片,重启会丢任务。

无论哪种方案,消费时要再查一次订单状态(用户可能刚好在这一刻付款了),关闭动作本身要对状态做 CAS(UPDATE ... WHERE status=待支付),保证幂等。

为什么用 Lua 脚本:Redis 执行 Lua 是单线程原子执行的,脚本内的多条命令不会被其他客户端插队。典型场景是”判断 + 扣减”这类需要原子的复合操作,比如秒杀库存扣减、分布式锁的释放(先比对 value 再删除)、限流计数。如果拆成多条命令从客户端发,中间就会有竞态窗口。它的限制也要知道:脚本不能太长(会阻塞整个实例)、不能在脚本里做耗时操作、集群模式下所有 key 必须在同一个 slot。

订单 id 什么时候生成:常见做法是在下单时就生成,且要保证全局唯一、趋势递增(便于 B+ 树索引写入)。方案有数据库自增段号(号段模式,一次取一批缓存在内存)、雪花算法(时间戳 + 机器号 + 序列号)、Redis INCR。不要用 UUID 做订单主键——无序会导致页分裂、插入性能差。另外要区分”订单号”和”支付流水号”:前者面向业务与用户,后者面向支付渠道,两者不该混用。

订单对账:核心是”三方对平”——本地订单/账务流水、支付渠道的对账文件、以及渠道实时回调三者对齐。工程上做 T+1 批量拉渠道对账文件,按渠道流水号匹配本地记录,把差异分成三类:本地有渠道无(可能是渠道未成功,需冲正)、渠道有本地无(回调丢失,需补单)、金额不一致(要人工介入)。差异结果落表并出报表,重试与告警都要有。

Codex 与 Cursor 的区别:Cursor 是 IDE 形态,强在编辑器内的补全、多文件重构和交互式改代码,人始终在环路里;Codex 一类是任务型 Agent,你给它一个目标,它自己读文件、跑命令、改多处代码直到完成,人在事后 review。面试里更好的答法是落到”我什么场景用哪个”:小步修改、需要看上下文时用 IDE 助手,批量机械改动、跨仓库重构时交任务型 Agent,并且明确说清你会怎么验收它改的东西。