顶点软件社招一二面:项目深挖与 HR 面
- 轮次
- 一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 自我介绍。
- 介绍一个自己做的比较有挑战性的项目——接口性能调优:用 javaagent 分析并通过线程池异步处理。
- 介绍项目里一个数据迁移的需求(涉及多张表、人员映射等)。
- 介绍项目中一个采用 Redis 分布式锁来同步序号的问题。
- Redis 分布式锁的实现原理(Redisson 框架)?lua + hash,field 是 UUID:threadId 是怎么回事?
- Java 死锁彻底治理。
- 介绍对 AI 的看法以及怎么使用。
- HR 面:平常怎么做需求的?需求怎么传递、和客户对接吗?
- HR 面:你们目前的项目属于外包性质吗?
- HR 面:手上有 offer 吗?怎么选择的?主要看重哪一点?
《参考解析》
接口性能调优怎么讲才有技术含量:不要从需求背景讲起(面试官已经点明了这个毛病)。正确顺序是:先给瓶颈定位过程——用什么手段发现的(javaagent 做方法级耗时埋点,或 arthas trace、火焰图),发现耗时集中在哪一段;再给方案与权衡——为什么选线程池异步而不是别的(哪些步骤可以并行、哪些必须串行、异步后如何汇总结果与处理异常);最后给结果——P99 从多少降到多少、压测怎么做的、有没有引入新问题(如线程池打满、上下文丢失)。
数据迁移需求怎么答:结构是”范围—映射—校验—回滚”。范围包括涉及多少张表、多少行、是否需要停机;映射包括字段映射规则、人员/组织这类维度如何对齐、历史脏数据怎么处理;校验包括行数对账、关键字段一致性抽样、以及迁移前后的业务验证;回滚包括是否支持重跑、幂等怎么做(按主键 upsert)、失败批次如何续跑。讲的时候一句”这块的难点是 XX 表的人员 ID 在目标系统里换了编码,我们做了映射表 + 全量比对”比罗列表名有用得多。
Redisson 分布式锁原理:加锁用 Lua 脚本保证原子性——HINCRBY lockKey field 1 记录重入次数,field 是 UUID:threadId 用来标识持有者(这样只有持锁线程能重入和解锁),首次加锁时 PEXPIRE 设置过期时间。解锁也用 Lua:先判断 field 是否存在、重入次数减到 0 才删除 key 并发布解锁消息。看门狗(watchdog)机制解决”业务还没执行完锁就过期”的问题——默认 30 秒租约,后台定时线程每 10 秒续期一次,直到显式解锁。要注意它只保证「同一时刻只有一个持有者」,不保证「锁一定不会被误释放」,所以仍要配合业务侧的幂等。
Java 死锁治理:定位手段是 jstack(会直接报 “Found one Java-level deadlock” 并给出线程与锁的持有等待关系)或 JConsole/Arthas 的线程视图,再结合代码定位加锁顺序。治理分三层:① 预防——统一加锁顺序(按对象 ID 排序后再加锁)、用 tryLock(timeout) 代替无限等待、缩小锁粒度、避免在持锁期间调用外部服务;② 检测——定期扫描线程状态并告警,或在关键路径记录锁等待时长;③ 兜底——对确实无法避免的场景引入超时与降级。
AI 的使用怎么看:要落到工程实践而不是态度表态。可以讲用在哪一环(代码生成、单测补齐、日志排查、SQL 生成)、怎么控风险(限定上下文与改动范围、产出必须过编译/类型检查/测试、关键路径人工 review),以及它带来的真实变化(某些重复劳动耗时明显下降,但设计决策依然得人来)。
面试表达本身也是考点:面试官明确点评”回答不要说太多需求,要把重点体现在技术方面”。社招面试官通常不懂你上家的业务背景,需求铺垫在他们听来是噪音。通用做法是先用一句话给结论(问题是什么、我怎么解的、结果如何),对方追问细节再展开——“结论先行、细节按需”。