小红书后端开发岗面经合集(一):工作流引擎、秒杀方案与 Agent 设计
- 轮次
- 多轮面试合集
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
面经 01 · 小红书后端开发岗(2026-09-11)
- 请做一下自我介绍
- 挑一个你做得最好的工作,深入介绍一下
- 这个工作流是如何搭建出来的?运行时怎样决定下一个节点?
- 这个工作流系统里最难的问题是什么?最后如何解决?
- 人工确认流程是怎么做的?如何防止重复确认和过期确认?
- Validator 校验体系是怎么设计的?如何处理跨字段和跨节点校验?
- 除了工作流本身,这个系统还有哪些难点设计?
面经 02 · 小红书后端开发岗(2026-08-24)
- 进程和线程的区别
- 垃圾回收算法讲一下
- 你有调过 JVM 的参数吗?
- 讲讲 Java 集合相关你熟悉的
- 你设置过 HashMap 初始化的参数吗?
- ArrayList 和 LinkedList 什么区别?
- TCP 和 UDP 区别
- JVM 内存模型中哪些是线程私有的?
- 手撕:两数之和
面经 03 · 小红书后端开发岗(2026-08-21)
- 项目中的难点以及如何解决的
- 有没有了解大数据相关的?
- Kafka 数据流转有没有经过磁盘?
- 数据库内容变化场景,下游服务是如何确保数据最终一致性的?
- 数据规模扩大,如何快速响应和扩容来应对突发流量?
- MySQL 是什么类型的数据库,Redis 是什么类型的数据库?
- 非关系型数据库你了解哪些?
- ES 你了解哪些?
- 算法:打家劫舍
面经 04 · 小红书后端开发岗(2026-08-20)
- 实现 LRU Cache
- 为什么要用 HashMap 和双向链表?除了 LRU 还有什么缓存策略,如何选用?
- 秒杀场景存在哪些问题,如何去解决?
- RocketMQ 事务消息是什么?
- 为什么要用 Lua 脚本?Lua 脚本为什么能够保证原子性?
- MQ 在这个秒杀方案里作用是什么?
- Redis 扣减成功之后,用户如何感知最终成功或者失败?
- Redis 操作成功和数据库之间能否保证一致性?
- 什么是乐观锁,如何实现乐观锁?
- Redis set 底层数据结构是什么?Redis 一共有哪些数据结构?
- zset 跳表的时间复杂度是多少?
- MVCC 原理,主要解决什么问题?
- MySQL 四种事务隔离级别分别是什么,使用场景是什么?
- 这条 SQL 该如何设计索引?如果查询不再使用 user_id,索引还能否生效?为什么范围查询之后后面的联合索引字段不能再使用?
- 讲一下 MySQL 索引结构,什么是回表?
- 三层 B+ 树大概可以存储多少条数据?B+ 树时间复杂度是多少?
- 为什么 MySQL 索引选用 B+ 树而不用 B 树?
- 这条 limit 大偏移量 SQL 执行很慢是什么原因?如何优化?子查询优化之后为什么速度会变快?
- 你现在这套秒杀方案,是否可以完整解决秒杀场景全部问题?还有哪些手段可以考虑?
- 讲一下 Coda 平台项目背景以及原理,做这件事的价值在哪?(问的虾皮实习项目)
- 谈一谈你对 Agent 的理解,Agent 完整设计包含哪几个关键环节?
- Agent 记忆该怎么做?什么时候需要保存记忆,什么时候读取记忆,读取多少长度的记忆?
- Agent 开发有哪几种执行模式,是否了解?
- 如何解决 Agent 意图识别不准的问题?
- 了解 RAG 吗?有没有实际使用过?
- RAG 效果如何评估?模型整体效果如何评估?RAG 效果不准该如何处理?
面经 05 · 小红书后端开发岗(2026-08-19)
- 共享屏幕看下项目,平时用自己的项目干什么?
- 介绍一下 Proxy
- Java 控制并发的操作,JUC 常用的类
- 实习遇到过的 JVM 问题
- MySQL 的锁和日志
- redo log 怎么做到 DB 灾难恢复?
- binlog
面经 06 · 小红书后端开发岗(2026-08-19)
- A2A 与项目的区别和联系,项目的价值?
- MVCC、事务隔离级别、锁
- MySQL 里面的 ref 和 range?
- MySQL Proxy 介绍一下
- MySQL 单机能抗多少连接?MySQL 能扛的连接为什么有限?
- MySQL 每个线程栈空间多大?
- Proxy 的 SQL 解析具体怎么做的?
- if-else 没有命中为什么执行速度很慢?
- C/S 模型两个机器,一方关机和宕机另一方有什么反应?
面经 07 · 小红书后端开发岗(2026-08-15)
- 请介绍一下实习公司,以及公司主要做什么
- 广告系统的优化策略目前是谁负责?你发现过哪些值得优化的点?具体怎么优化?
- 你是如何进行技术选型的?从稳定性角度需要关注哪些指标?
- 报表系统如何设计?数据如何入库、读取和查询?这些工作是你负责的吗?
- 请介绍广告中台整体设计,以及 MCP 封装后的数据如何提供给其他系统
- EasyExcel 流式读取、Sheet 并行和批量插入主要解决什么问题?
- 为什么实习三个月后选择离职?
- MCP 数据进入 Agent 后,后续的分析输出和投放优化链路你是否参与?
- MyPrAgent 解决什么问题?整体 Agent 架构如何设计?
- Code Review Agent 的效果如何评估?关注哪些指标?做过哪些迭代?
- 你实际使用或实现过 ReAct 吗?
- 你们有没有把项目上传到 GitHub?
面经 08 · 小红书后端开发岗(2026-08-10)
- 项目设计问题,偏架构层面,非常规八股
- 用过 OAuth 吗?怎么实现的?
- MySQL 中一条 SQL 语句的执行过程
- 有没有看过主流 Agent 应用的上下文管理策略?
- 手撕:二叉树层序遍历、有效括号字符串(无需测试,口述思路 + 核心代码即可)
- 场景题:设计一个群聊 Agent,可以 @ 它回答问题或干活,如何管理权限、上下文与并行请求?
- 计算机八股:UDP 与 TCP 区别、TCP 怎么保证可靠、进程与线程的区别
- OpenAI ChatCompletion 协议的请求体 JSON 中有哪些常用字段?
面经 09 · 小红书后端开发岗(2026-08-06)
- 哪一届的?大四还是准大三?
- 假设你现在要参与一个电商活动,有 5000 万的商品,你会怎么去设计这个缓存?
- 为什么要用哈希?
- 过期时间会设置多久?
- 如果有一个爆款商品,10 万的 QPS 全部打到 Redis 和 MySQL,MySQL 崩了,这是个什么问题?
- 击穿、穿透区别
- 热点 Key 如何解决?如何发现热点 Key?如何发现它 QPS 很高?
- 数据库缓存一致性
- Redis 如何处理 Key 过期?Key 淘汰策略
- Redis 分布式锁:如果设计分布式锁,需要考虑什么?Redis 设计锁会考虑哪些技术上的问题?TTL 多久?NX?EX?不用 Redisson 怎么实现分布式锁?watchdog 干嘛的,为什么续期?还有其他要考虑的吗?为什么你不干脆用 Redis 去写?
- ZSet 数据结构
- select * from orders where userId = XXX order by createtime desc limit 20,怎么建索引最好?
- order by 原理
- 深分页解决方案,为什么子查询能优化?为什么数据量小也能优化深分页?
- ZSet 为什么要用跳表?为什么不用其他数据结构?时间复杂度是多少?什么时候退化成 n?
- MVCC 是什么?事务隔离级别?为什么幻读不能完全解决?
- Agent 是什么?如果让你设计一个 Agent,你会怎么考虑它的全部执行流程?
- Agent 和普通 chatbot 的区别
- Agent 有哪些模块?分别解决什么问题?
- 讲一下模型决策是什么
- RAG 是什么?解决什么问题?
- ReAct 是什么?Plan and Solve 是什么?详细执行流程、适合什么场景、优缺点分别是什么?
- 你觉得 Plan and Solve 更好吗,为什么?
- RAG 的详细流程、会有什么问题、你觉得的处理方案是什么?
- chunk 策略是什么?chunk 排序完如何优化效果?怎么评测效果,效果不好还能怎么优化?
- 数据集怎么来?你自己标注吗?
- 指标和方案、优化方案——你怎么知道这个指标好还是不好?怎么评估?
- 讲一下 Agent 的记忆,什么时候开始触发记忆?
面经 10 · 小红书后端开发岗(2026-07-11)
- 展开聊一下你的 AI 项目
- 做这个事情的起因是什么?技术选型和方向判断是什么?落地过程中遇到哪些难点?项目上线以后有没有人用?
- 展开讲讲微调
- 用 2000 条数据去做微调,原理上怎么能够提升准确率?
《参考解析》
面经 01 · 工作流引擎与校验体系
-
工作流引擎的调度与人工节点的幂等:这类项目面试官一定会往下钻到「运行时怎么决定下一个节点」。答题要能说清三件事:流程定义怎么存(节点与边的有向图,边带条件表达式,存库或存配置中心,版本化以便灰度);调度怎么走(解释器模式或状态机驱动,每次执行完一个节点,用当前上下文求值所有出边的条件,命中就走,都不命中要明确是报错还是走默认分支);状态怎么持久化(每个节点的执行结果落库,支持从中断处恢复,避免长流程常驻内存)。有条件的话补一句并发与超时:同一实例要加锁串行推进,外部节点要设超时与重试,重试必须幂等。 人工节点是这类系统最容易出 bug 的地方。防重复确认靠「状态机 + 乐观锁」:任务有明确的待确认 / 已确认 / 已过期状态,确认时用条件更新(where status = 待确认)或版本号,更新行数为 0 就说明已经被处理过,直接返回幂等结果。防过期靠「任务带过期时间 + 定时扫描」:到点未确认就把任务置为超时,按流程定义的超时分支继续(自动通过、驳回或升级给上级);扫描要能补偿,别只依赖内存定时器。再叠一层幂等键(流程实例 ID + 节点 ID)做唯一约束,重复请求在数据库层就被拦住。
-
Validator 的分层设计:校验规则按成本与依赖分层是标准答案——结构校验只看必填、类型、格式和长度,纯本地计算,可以放在入口最先跑;业务校验处理跨字段、跨节点与状态约束(金额关系、状态是否允许该操作),要读流程上下文;外部校验需要查账户、汇率或渠道状态,有网络开销和失败概率,必须设超时、做缓存、失败时区分「确定不合法」和「暂时查不到」——后者不能直接判失败,要进重试或人工处理。跨节点校验的关键是上下文快照:每个节点执行后把必要字段写进上下文,校验时从那份快照取值,而不是回头查数据库的最新状态,否则会出现「校验时通过、执行时已变」的竞态。规则本身建议做成可配置、可版本化,出错时能说清是哪条规则、哪个字段拦下的。
面经 02 / 04 · Java 基础、集合与秒杀方案
-
Java 基础、集合与 LRU 缓存实现:调参要能报出场景而不是罗列参数——堆大小与新生代比例(-Xms / -Xmx / -Xmn)、GC 器选择与停顿目标(G1 的 MaxGCPauseMillis)、OOM 时 dump(-XX:+HeapDumpOnOutOfMemoryError)、元空间上限;并说清调参前先看 GC 日志和监控,没有数据的调参是猜。HashMap 初始化参数问的是扩容成本:默认容量 16、负载因子 0.75,元素数超过阈值就翻倍并 rehash,所以能预估大小时直接给定容量(按「预期元素数 / 0.75 向上取最近的 2 的幂」)可以省掉多次扩容。ArrayList 是数组、随机访问 O(1)、尾部扩容摊还 O(1)、中间插入要搬数据;LinkedList 是双向链表、插入删除 O(1) 但要先遍历,节点额外内存大,实际业务里 ArrayList 用得更多。JVM 内存区里线程私有的三块:程序计数器、虚拟机栈、本地方法栈;堆和方法区(元空间)是线程共享的。 LRU 的标准实现是哈希表 + 双向链表:哈希表 O(1) 定位,双向链表维护访问顺序,get 命中就把节点移到头部,put 时容量满了就淘汰尾部,新节点插头部;用带哨兵头尾的链表能省掉大量边界判断,漏更新前后指针、容量为 1、更新已存在的 key 是三个经典写错点。其他策略要能对比:FIFO 只看进入顺序、LFU 按访问频次淘汰(解决 LRU 在偶发批量扫描下被污染的问题)、W-TinyLFU(Caffeine 用的)用频率草图做准入判断,在多数读密集场景命中率优于纯 LRU;还有 TTL 过期、随机淘汰、以及业务侧的热点探测。选用判据是访问分布:有明显热点且访问频次稳定用 LFU 系,访问有强时间局部性用 LRU,混合负载用 W-TinyLFU。
-
秒杀方案与 Lua 的原子性:秒杀的核心矛盾是「瞬时高并发 + 库存不能超卖」。常见链路是:入口限流与答题/验证码挡机器流量 → 库存预热到 Redis → 用 Lua 脚本把「校验库存 + 扣减 + 记录用户」合成一次原子操作 → 扣减成功再异步下单(发 MQ),数据库层用「库存 > 0」的条件更新做最终校验 → 前端轮询或 MQ 回调告知下单结果。为什么必须用 Lua:CHECK 和 DECR 是两条命令,中间可能插进其他请求,导致超卖或重复扣减;Lua 在 Redis 里整体执行不被插队,所以能保证「检查与扣减」的原子性。MQ 在这里承担削峰与解耦:把下单、发券、通知这些非关键路径的写操作从主链路剥离,失败可以重试。用户如何感知成败:扣减成功只代表排队成功,真正结果通过 MQ 消费后写订单,前端用轮询或推送查状态,并给订单设超时未支付自动回补库存。Redis 与数据库的一致性无法做到强一致,工程目标是最终一致:以数据库为准、Redis 只做预扣,靠对账任务扫异常并补偿。面试官通常最后会问「这套方案还有哪些问题」,答的方向是热点 Key、Redis 单点与主从切换丢数据、Lua 脚本执行时间阻塞其他请求、以及库存回补的幂等。
面经 04 / 09 · MySQL 与 Redis 深入
-
索引、MVCC 与深分页:索引结构的标准答法是 B+ 树——多路平衡、只有叶子节点存数据且用双向链表相连,所以范围查询和排序友好、树高很低(三层大概能放千万级到亿级的行,取决于主键大小和页大小,答题时给「千万级」这种量级加推导过程即可),而 B 树每个节点都存数据,同样层数能放的行数更少、范围扫描还要中序回溯。回表是二级索引只存索引列与主键,查其它列要拿主键再走一次聚簇索引;覆盖索引就是让查询需要的列都在索引里,直接省掉回表。联合索引的最左前缀决定了跳过前导列或前导列用了范围查询之后,后面的列就无法再走索引定位(只能做 ICP 过滤),这是「范围查询之后后面的字段失效」的原因。MVCC 靠隐藏列(事务 ID、回滚指针)、undo log 版本链和 ReadView 实现一致性读:读已提交每次查询都生成新的 ReadView,可重复读在事务内复用同一个 ReadView,所以前者会看到别人新提交的数据、后者不会;幻读在快照读下基本被解决,但当前读(for update、加锁读)仍可能插入新行,要靠间隙锁(next-key lock)挡住,这就是「幻读不能完全解决」的落点。深分页慢的原因是
limit 1000000, 10要先扫描并丢弃前一百万行,优化方向是游标分页(记住上一页最后一条的排序键,用 where 收窄)、延迟关联(先用覆盖索引拿主键再回表取数据)、以及必要的联合索引让排序走索引避免 filesort。 -
Redis 数据结构与分布式锁:五种基础结构对应不同的底层实现:string 是 SDS(预分配、二进制安全、记录了长度所以取长度 O(1));list 在元素少时用 ziplist / listpack、多了转 quicklist(链表套紧凑列表);hash 小数据量用紧凑列表、大了转哈希表;set 是整数集合或哈希表;zset 是哈希表 + 跳表。跳表被选中是因为它实现简单、范围查询与排名都好做、并发下比平衡树容易改(Redis 本身单线程,但跳表的代码量和维护成本仍占优),平均查询复杂度 O(log n),最坏情况退化成 O(n)(索引层没能有效跳过)。分布式锁的最小实现是
SET key value NX PX ttl,value 用「客户端 ID + 线程 ID」保证只有持有者能删;删锁要先比对 value 再删,这两步必须用 Lua 保证原子,否则可能误删别人的锁。Redisson 补的是可重入(Hash 结构记重入次数)、看门狗续期(默认每 10 秒把 30 秒的 TTL 续回去,避免业务没跑完锁就过期)、阻塞等待与公平锁。TTL 要按业务最长执行时间给,但没有续期的固定 TTL 总有失效窗口,所以最外层还必须幂等;集群模式下主从异步复制可能丢锁,要接受「锁只能降低并发,不能替代幂等」这个前提。
面经 03 / 04 / 08 / 10 · 项目、一致性与 AI
-
数据一致性与扩容:数据库变更后让下游保持一致,主流是订阅 binlog(Canal / Debezium)异步投递,配合幂等消费、按主键顺序处理、以及失败重试与死信兜底;要能说清为什么不用双写——双写在写库成功、发消息失败时就会丢事件,而 binlog 是数据库自己的提交日志,天然与事务对齐。对账是最后一道闸:定时比对上下游的关键计数或校验和,发现偏差告警并自动修复。突发流量下快速响应与扩容的思路分三层:入口限流与排队保护、无状态服务水平扩容(提前做容量评估与压测,K8s HPA 按 QPS 或 CPU 触发,注意冷启动与连接池预热)、有状态部分(数据库、缓存)靠读写分离、分库分表、热点打散与本地缓存兜底;还要有降级预案(关掉非核心功能、返回缓存旧值)。
-
Agent 的完整设计与 RAG 的评估调优:一个可用的 Agent 至少包含规划(把目标拆成步骤)、工具调用(Function Calling)、记忆、以及执行循环与终止条件这几块。记忆要分开讲:短期记忆是当前会话的上下文窗口,长期记忆是跨会话持久化的用户偏好与事实,通常存向量库或结构化存储。写入时机是「产生了稳定的、未来还会用到的事实」(用户偏好、项目约束、已确认的结论),而不是每轮对话都写;读取时机是任务开始时按当前目标检索,或对话中出现需要个性化处理的信号时检索;检索长度要按 token 预算给,比如 top-k 加阈值过滤再做 rerank,宁可少而准——塞太多不仅贵,还会把关键信息淹没。执行模式常见的有 ReAct(思考-行动-观察交替,边做边调整)、Plan-and-Solve(先出完整计划再执行,路径清晰但不灵活)、以及两者的混合(先规划大步骤,每一步内部用 ReAct)。意图识别不准的治理方向是:把意图收敛成有限集合并让模型只在这个集合里选、补 few-shot 例子与业务黑话词典、低置信度时走澄清反问而不是硬猜、把上游的路由判断交给规则兜底、并把错分样本回流做评测集。 完整链路是「文档解析与清洗 → 切块 → 向量化 → 入库 → 查询改写 → 召回(向量 + 关键词混合)→ 重排 → 拼上下文生成 → 引用与兜底」。每一环都有典型问题:解析丢表格与层级、切块切断语义(按结构切、加重叠、给每块带上标题路径)、召回不足(混合检索、多路召回、HyDE)、召回太杂(rerank、元数据过滤)、以及模型不按材料回答(prompt 里要求引用原文、无依据就说不知道)。评估要拆开看两个层面:检索层看命中率、召回率、MRR、NDCG;生成层看忠实度(有没有编)、答案相关性、以及端到端的任务成功率。没有标注数据时可以用「用强模型打分 + 人工抽检 + 线上用户反馈」三路凑评测集,并对生成答案做二元判定(对 / 错 / 部分对)。效果不好先定位是检索没召回到,还是召回到了模型没用上——这两类的修法完全不同:前者改切块与召回策略,后者改 prompt、上下文排序或换模型。