面灵AI→

恒生电子 AI 应用开发(杭州)一面面经

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

《面试题目》

  1. 简单自我介绍。
  2. 实习 6-8 月项目:你做过最难或最有成就感的工作是什么?
  3. A 君 Agent 项目:是入职前就存在、你只是参与而非主导开发吗?
  4. Agent 选型:为什么不基于 local agent,而是选择软管和 rough?
  5. 开源 Agent 框架:Masquerade、DeepAgent、DSH 你是否了解?
  6. 框架选型:能不能直接基于 DeepSeek Agent 做开发?会存在什么问题?
  7. 项目技术选型是谁决定的?
  8. Redis 有哪几种数据结构?
  9. Redis 持久化分哪几种?各自的优缺点是什么?
  10. 什么场景下 AOF 会丢数据?
  11. ThreadLocal 在线程池复用场景会有什么问题?
  12. ThreadLocal 数据污染问题有什么解决方案或相关框架?

《参考解析》

项目深挖与「你是不是主导者」。这场面试前七题都在验真,套路是:先让你讲最难或最有成就感的工作,再追问项目在你入职前是否已存在、选型是谁定的、你做了哪部分。准备时要把项目拆成三层回答——业务问题(谁在用、解决什么痛点、上线前后指标变化)、技术方案(架构图、关键模块、数据流)、你的贡献(独立完成的模块、做过的关键决策与取舍、踩过的坑)。如果确实是参与而非主导,最稳的回答是明确划界:「框架和选型是团队既定的,我负责 X 模块,在其中做了 Y 决策」,然后立刻用一个具体的技术细节证明你真的深入过(比如某个参数为什么取这个值、某次故障怎么定位的),比含糊地认领整体设计可信得多。

Agent 选型:为什么不自研、local agent 与开源框架的取舍。被问「为什么不基于 local agent」时,要点是把需求画成约束:local agent(跑在本地的编码型 Agent)强在文件与命令的本地操作,但缺少多租户隔离、可观测、权限与审计、以及服务端并发调度这些生产必需的能力;如果业务是给企业客户提供问答与流程自动化的服务端 Agent,需要的是可编排、可持久化、可监控的运行时,而不是一个绑定在个人机器上的工具。选 LangGraph 这类图编排框架而不自研,是因为状态机、条件边、循环与重试、人工介入、断点恢复、流式事件这些骨架都已经被大量场景验证过,自研省下的只有依赖成本,却要自己踩并发与状态合并的坑;如果选的是轻量框架,则要能说清它在什么规模下会不够用(比如缺 checkpoint 恢复、缺多 Agent 协作原语)。至于「能不能直接基于 DeepSeek Agent 做开发」,答案是可以但要看清代价:模型厂商的 Agent 产品通常把工具生态、执行环境与对话状态都封在自己的一套里,能拿到的定制点有限,难以接入企业内部系统与自定义的权限模型,也无法替换模型或做细粒度的上下文控制;一旦业务需要私有化部署、审计留痕或按客户做多租户隔离,就得退回自建编排层加直连模型 API 的路子。

Redis 的数据结构与持久化。常用结构有 String(缓存、计数器、分布式锁、位图与 HyperLogLog 也基于它)、Hash(对象字段的部分更新,比如购物车)、List(队列与栈,lpush 加 brpop 做简单消息队列)、Set(去重、共同好友这类交并差运算)、ZSet(排行榜、延迟队列,按分数排序且支持范围查询),此外还有 Stream(带消费组与 ack 的消息流)、Bitmap、Geo、HyperLogLog 这些扩展类型。选型的判据是「需要什么查询模式」:要按分数范围取就用 ZSet,要去重与集合运算就用 Set,要部分字段读写就用 Hash,避免整存整取带来的序列化开销。

持久化有两条路。RDB 是某个时间点的全量快照,通过 fork 子进程写盘,文件紧凑、恢复快、对主进程影响小,缺点是两次快照之间宕机会丢数据,快照期间 fork 与写时复制会带来内存与延迟抖动。AOF 记录写命令,appendfsync 三档(always 每条刷盘最安全最慢、everysec 每秒刷盘、no 交给操作系统),always 基本不丢但性能差,everysec 是最常用的折中,最坏丢一秒左右的数据;AOF 文件会随命令累积膨胀,需要 BGREWRITEAOF 重写压缩。生产上通常两者同时开启,重启时优先用 AOF 恢复(更完整)。被追问「AOF 什么场景会丢数据」,按档位答:everysec 下在两次刷盘之间宕机,最后约一秒的写入会丢;no 档由内核决定刷盘时机,可能丢几秒甚至更多;always 也不是绝对,主从环境下若主库刷盘成功但故障切换时从库未同步到(异步复制),切换到从库后仍会丢这段数据;此外 AOF 重写期间新写入先进重写缓冲区,若子进程写盘失败或进程被杀,也可能只保住了旧文件;磁盘写满、fsync 被阻塞这类系统级故障同样会造成持久化中断。至于「应用内存与 Redis 内存的区别」这类延伸题,要能讲清 Redis 是独立进程、内存独立核算且有 maxmemory 与淘汰策略(LRU/LFU/随机/TTL),而应用内缓存在 JVM 堆里、受 GC 与堆大小限制、多实例之间不共享。

ThreadLocal 在线程池下的问题与解法。ThreadLocal 的数据存在每个 Thread 的 ThreadLocalMap 里,键是 ThreadLocal 的弱引用、值是强引用。用在线程池里有两个坑:一是线程复用导致的串数据,线程归还池后没清理,下一个任务在同一线程上跑就可能读到上一个任务留下的值,典型事故是用户 A 的租户 id 或身份证号出现在用户 B 的请求里;二是内存泄漏,ThreadLocal 对象被回收后键变成 null,但值仍被线程强引用,只要线程活着(池里的核心线程几乎永生)这块内存就回收不掉,最终可能老年代堆积甚至 OOM。正确的用法是三步:避免用 static 加可变对象长期持有;在 try 里 set、在 finally 里 remove,异常路径也不能漏;用 Spring 的请求上下文时不要跨线程传递而不做处理。跨线程传递的框架有阿里开源的 TransmittableThreadLocal(TTL),它通过装饰线程池的线程工厂把父线程的值快照传递到子线程并在任务结束后还原;InheritableThreadLocal 只在线程创建时复制一次,对线程池这种「线程早已创建」的场景无效,这是常见误区。此外还要注意 ThreadLocalRandom 与 InheritableThreadLocal 的区别,以及响应式编程里 ThreadLocal 会因为线程切换而失效,需要 Reactor 的 contextWrite 这类显式上下文机制。