面灵AI→

小红书风控研发一面到三面面经:从归因 Agent 到秒杀链路设计

轮次
一面、二面、三面
时间
2026-10
来源
牛客网

《面试题目》

  1. 请做一两分钟的自我介绍。
  2. 你后续的职业规划是什么?想做偏技术基建方向还是业务方向?
  3. 你自己有什么兴趣点吗?
  4. 介绍一下风控归因 Agent 这个项目的背景,它主要解决什么问题?你是怎么实现的?
  5. 你做这块的难点是什么?
  6. 架构演进过程中,你是怎么发现问题的?怎么判断之前的方案确实需要重构?
  7. V1、V2、V3 不同版本的架构选型是怎么推导出来的?
  8. 怎么量化上下文隔离或技术优化带来的成本消耗降低?
  9. 是否存在「先污染后治理」:一开始设计时就能预判 Token 消耗大,为什么不一开始就选更好的方案,而是先跑起来再降?
  10. 三级数据查询的历史数据回溯机制,怎么保证数据一致性?
  11. 你对风控业务有全局了解吗?风控是做什么的?系统架构是什么样的?
  12. 你们的系统架构有几个系统?每个系统主要负责什么功能?
  13. 你觉得在风控实习过程中,成长最大的是什么?
  14. 平时在工作或日常学习中,你是怎么学习 AI 的?
  15. 你提到 Claude Code 的三层架构,可以详细讲一下它是怎么实现的吗?
  16. 前段时间比较火的 Harness 概念,有没有了解过?
  17. 年初比较火的龙虾 OpenCloud,自己有没有尝试过?
  18. 自己有没有了解过大模型是怎么训练的?有没有训练过模型?
  19. 电商有个热点福利品,库存几十万,会触发秒杀,你作为秒杀链路负责人,怎么设计优化整条链路保证高 TPS?
  20. Redis 库存扣减为什么要用 Lua 脚本?原子性你是怎么理解的?
  21. 缓存一致性:本地缓存和 Redis、Redis 和 DB 之间的一致性怎么保证?
  22. 数据库单行 TPS 上限:Redis 扣减后异步扣 DB,单行有 TPS 上限,1 万并发怎么解决?
  23. 请求合并的落地细节:怎么把 100 次请求聚合成一次写 DB?怎么感知 Redis 数据变更?
  24. 给定链表头节点 head,反转链表并返回新头节点,说一下思路并写代码。
  25. 反问:团队做什么业务?
  26. 反问:秋招面试流程是怎样的?
  27. 反问:AI 时代校招生需要什么能力、该如何提升?
  28. 请先做一个自我介绍。
  29. 你拿到字节的 offer 了吗?
  30. 你了解小红书的业务吗?面试小红书主要吸引你的点是什么?
  31. 你这一年多的时间,主要的精力分配是什么样子的?分别投入在哪几块?
  32. 处置平台主要提供什么样的能力?你能大概讲一讲吗?
  33. 你们这一块治理是服务于哪些业务线?
  34. 你讲一下你做的核心的工作吧。
  35. 这个智能体主要解决什么问题?它肯定不是一个在线的风控吧?
  36. 拿了一个客诉,需要判断为什么广告主被风控了,这个场景你怎么处理?
  37. 这个智能体是你自己搭建的吗?有没有用什么开源框架?
  38. 当时为什么没有依托 Codex 和 CC 去开发 Skill 的方式去做,而是自己做一个智能体?
  39. 为什么基于内部框架,不基于开源的 OpenClaw 或者 Horus 这种框架?
  40. 这个效果怎么样?从业务的收益角度讲一讲。
  41. 框架给你的开放程度多高?上下文管理、效果评测,哪些是框架提供的,哪些是你实现的?
  42. 你有没有调研过像 CC 的 Compact、Old Code Compress 这种机制,它们背后执行命令之后具体做了什么?
  43. 你有没有调研过 Codex 的压缩方式?他们也是丢进去路径吗?
  44. 稳定性这一块你是做了什么?我看到你写了个稳定性的技术沉淀。
  45. 你觉得 AI 时代,你作为工程或计算机专业的同学,和文科生以及没学过计算机原理的同学,未来之间最大的差异是什么?你最大的优势是什么?
  46. 你觉得你最大的优点和当前阶段需要提升的点是什么?
  47. 希望 base 在哪边?我们主要是在杭州和上海这边。
  48. 你这边有没有什么问题?
  49. 你一面的时候,你觉得有没有回答不好的地方?之后有去看看吗?
  50. 三面追问:这个项目的收益怎么样?挑战和难点在哪里?

《参考解析》

秒杀链路的整体设计,核心是「把流量挡在数据库之前」。 分层削峰:入口层把静态资源全部 CDN 化,用按钮置灰、答题、验证码把瞬时并发打散,网关按用户维度和商品维度限流;前置校验层在 Redis 里做活动时间、白名单、限购数量、库存是否充足的无状态判断,绝大多数请求在这一层就被拒掉;扣减层在 Redis 里原子扣减库存,完全不碰数据库;异步层把手里的请求投进 MQ,由消费者下单落库;数据层只做最终写入和对账。热点要单独隔离:单个商品用独立队列、独立 key,避免一个 SKU 打满整个集群;更彻底的是库存分桶——把几十万库存拆成 N 份 key,按用户 ID 哈希落桶,单 key 的 QPS 直接降到 1/N。防超卖靠三重保险:Redis 原子扣减、数据库唯一约束、业务幂等键,宁可少卖也不能超卖。最后一定要有兜底:MQ 消费失败要有补偿与对账任务,活动结束用 DB 的准数反向校正 Redis。

Redis 扣减为什么必须用 Lua,以及「原子性」到底指什么。 因为「读库存 → 判断是否大于 0 → 扣减 → 记录该用户已购」是四步逻辑,单条 Redis 命令表达不了,而拆开执行会被并发请求插进来,导致超卖或重复扣。EVAL 把整段脚本交给 Redis 的单线程执行模型,脚本执行期间不会插入其它命令,于是获得了原子性——注意这是「不可分割」意义上的原子,不是数据库事务那种失败可回滚的原子,所以脚本里要尽量避免中途失败留下半截状态。相比 WATCH + MULTI 的乐观锁,脚本方案不用重试、少一个 RTT,高并发下不会因版本冲突大面积失败。工程细节三条:脚本要短,别在大 key 上跑循环或做复杂计算,否则阻塞整个实例;集群模式要用 hash tag 把相关 key 路由到同一个 slot,否则直接报 key 不在同一节点;限购用的去重集合要单独设过期时间,活动结束自动回收。

缓存一致性要分两条链路看,而且目标不是强一致。 一条是本地缓存与 Redis 之间,一条是 Redis 与 DB 之间。Redis 与 DB 主流是 Cache Aside:读走「先读缓存、未命中回源 DB 再回填」,写走「先更新 DB、再删除缓存」——删缓存而不是更新缓存,因为两个并发写时「更新缓存的顺序」很容易和「落库顺序」相反,反而留下旧值。删缓存失败的兜底有三招:延迟双删(更新 DB 后删一次,隔几百毫秒再删一次,覆盖「读线程在写线程删缓存之前读到旧值、之后才回填」的窗口)、订阅 binlog 用异步任务删(Canal 这类,解耦且不怕业务漏删)、给 key 留一个较短的 TTL 作最后防线。本地缓存与 Redis 之间麻烦一些,因为进程内缓存没法被外部主动失效,得靠广播失效(Redis pub/sub 或 MQ 广播)或者把本地 TTL 设得很短再配主动刷新。最实在的判断标准是业务能容忍多久的脏数据:秒杀库存这种不能错的场景就别谈最终一致,直接以 Redis 为准、DB 只当账本。

单行 TPS 上限是热点写入的物理瓶颈,解法是别让所有请求抢同一行。 InnoDB 对同一行的更新要串行加行锁,一个事务还要写 redo/undo,单行热点更新的吞吐通常只有几千 TPS 量级,远低于整库几十万 QPS 的能力上限。所以「Redis 扣完后异步扣 DB」在 1 万并发下依然会堵在那一行:事务排队等锁、连接池被占满、上游超时雪崩。三层解法。第一层是拆行,把一个 SKU 的库存拆成 stock_1 到 stock_N,按用户哈希落桶,写并发度直接乘 N,代价是库存要能按桶再平衡、退库存要能找回原桶。第二层是请求合并,把 N 次扣减聚成一条 UPDATE stock SET amount = amount - #{total} WHERE sku = ? AND amount >= #{total},N 次锁等待变成 1 次。第三层是异步化加顺序化,MQ 按 SKU 分区保证同商品串行,消费者批量刷写,DB 只承担削峰后的量,最终靠对账任务把差额校正回去。

请求合并怎么落地:关键在「攒批」和「变更感知」两个动作。 攒批的常见做法是在应用侧或一个无状态网关维护按 SKU 聚合的队列,用「攒够 N 条」或「等一个几毫秒的时间窗」触发批量提交,前者适合流量平稳,后者适合尖峰,实际会取两者先到。提交时以 DB 的实际影响行数为准:影响行数为 0 说明库存不足,这批里谁成功谁失败要按入队顺序回退并给用户返回失败,所以队列元素必须带请求 ID 才能精确 ack。变更感知有几种路数:Redis 的 keyspace notification 最省事,但它不保证送达、断连期间的变更会丢,只能当触发信号而不是事实来源;可靠一点的是让扣减那一侧把变更写进 Redis Stream 或 List 当变更日志,消费者按消费组读取并 ack,天然支持重放;最粗暴的是消费者按固定频率批量捞取待处理流水。要提醒的是合并会放大单次失败的爆炸半径,批量写失败必须留整批重试或逐条降级的路径,不能一条 SQL 挂了就把整批请求丢掉。

架构演进与「先污染后治理」怎么答才不失分。 这类追问考的是技术判断力,不是让你认错。组织答案的结构是:当时的约束条件(工期、流量规模、团队认知边界)→ 什么信号触发你意识到方案不够用了(要可量化,比如 Token 成本曲线、P99 延迟、错误率、维护人力)→ V1、V2、V3 各自的取舍边界在哪 → 为什么当时不做一步到位。承认「先跑起来再优化」在快速验证期是合理的,但要能说出你为此留的钩子:接口抽象、可替换的实现层、埋点。成本量化的口径建议固定成「单次调用的 token 数 × 调用次数 × 单价」,再往下拆成上下文长度、重试次数、模型档位三个可调项,这样优化前后能直接算成钱,而不是只说一句「快了很多」。