恩希云 一面 JAVA 社招两年 面经
两道算法题 讲思路(第一道ac,第二道优化思路没想到)有一道让我判断 abcd第一个不重复的元素我说的 当遍历到a时 检测字串bcd有没有重复元素面试官时间复杂度为 平方n 有没有优化思路?
.....没想到,点了?
面完想起了 统计个数
- 介绍一下你自己
面试官:请做一下自我介绍。
- 面试题
Q1说一下行锁升级为Redis分布式锁的背景和实现方案。
回答:业务背景是多台机器执行异步任务,抢占任务竞争激烈,最终选择了Redis分布式锁而非乐观锁或MySQL行锁。
复盘答案:
对比行锁与乐观锁以及分布式锁的区别以及场景。行级锁: 主从也能用,就是 性能低乐观锁:
UPDATE task
SET status = 执行中, version = version + 1
WHERE status = 0
AND id IN (1,2,3,4)
可能导致 部分失败Redis分布式锁:保证一批任务的原子性,要么这一批全部抢占成功,要么全部失败。
Q1死锁是啥?
A:关于死锁,虽然我没遇到过,但知道死锁发生的四个条件:资源互竞争、资源不可剥夺、环路等待、请求保持。破坏条件的方式包括一次性申请完资源,或给锁设置过期时间做兜底。
复盘:
差不多
Q2Redis除了锁还用来做什么?
答:做消息查询的缓存,以及防重复消息。
追问:怎么解决缓存一致性问题?
周杰:Redis和MySQL本质解决不了实时一致性,我们采用最终一致性方案——延时双删。先删缓存,再更新数据库,然后再删一次缓存,前后两次删除保证缓存清除。
复盘:缓存一致性怎么保证
1.过期时间兜底2.更新mysql后删除redis
3.reids订阅mysql的bin log日志,使用阿里canal组件
Q3解释一下冷热数据。
答:我们有定时任务(每小时、每分钟都有),业务真正需要观测的是即将发生的事件(近2小时内),其他属于冷数据。我们把近2小时的时间点放入Redis,用适当数据结构不断检查是否到点,到点就拿出来给执行层。冷数据有迁移服务不断生成后面要执行的数据,存在数据库里。
复盘:
差不多
Q4任务量大时怎么处理?
答:考虑过分表问题。调研过美团、阿里的组件,但我们想做自己有分库分表能力的方案。做了个治理服务,当表大于400万(阿里推荐500万,我们选400万做缓冲)时就重新分表,新任务在新表执行,旧表保留执行记录。冷数据直接归档,热数据(单表内容)用ES解决大表查询问题。
复盘:
应该回增加worker执行者机器的。(这里应该 面试就寄寄了)
Q5离职原因?之前工作强度怎么样?
答:是的。当时主要是家里母亲要手术,公司不能请长假,我也请了很多次假,最终主动离职。在休息期间也在自学技术、看专业书籍。
答压力比较大,工作压过来时,有时候周天晚上10点钟也在开会,有点累了。但其实感觉还可以,就是一个一个任务完成,有攀越高峰的感觉。
面试官:你用Claude Code做什么?
答:来需求后,先讲清楚任务背景和角色(用提示词工程)。比如找开源项目时,会让Claude总结项目、生成README。如果是开发数据面板,会mock假数据。也会用来做单测。
复盘:1.首先用plan模式 生成 整体框架
2.生成前要求清楚 明确技术栈、项目要求、功能点
3.生成 CLAUDE.md 方案文档
4.起一个子代理 检查、写单测
5.skills优化(具体用啥skills还在网上学)
大体这几个架构、Code Review、单元测试、Spring Boot、微服务
Q6线程池用的啥:
fixed线程池
核心参数7个:最大线程数、核心线程数、阻塞队列、最大超时时间、超时时间单位、线程工厂、拒绝策略。
分配流程:先创建线程,看核心线程是否满载。满了进阻塞队列(无界队列直接进),队列满了再扩到最大线程数。最大线程数也满了就进入拒绝策略(默认AbortPolicy)。
复盘:差不多
Q8
ThreadLocal:
本质是HashMap,给每个线程分配副本。
缺点是可能内存泄漏,因为Key是弱引用,键被删除后Value释放不了。建议设置为static或不要声明过多。
复盘:
1.threadlocal实现线程隔离,给每个线程分配副本(放弃源码解释了,记不清)2.内存泄漏问题,因为key是弱引用(GC触发就回收),value是强引用,当key的回收了之后,value就不会被回收。
解决方法: 用完remove
Q9
MySQL索引失效哪些:
最左匹配原则失效(模糊查询%在左边)。
函数计算导致失效。
范围查询导致后续索引失效(如a、b、c三个条件,b产生范围查询,c的索引失效)。
复盘:
Q10 MVCC介绍下:
答:解决读写冲突,与Undo Log一起实现ACID中的隔离性。
Undo Log每行隐藏两列:事务ID和回滚指针(指向上一个版本)。
Read View包含:当前事务ID、最大活跃ID、最小活跃ID、最大事务ID。
判断规则:事务ID小于最小活跃ID(已提交,可见);大于最大事务ID(未提交,不可见);在活跃事务列表中(活跃中,不可见)。
解决部分幻读问题,但解决不了当前读(快照读和当前读混用场景)。
复盘:
差不多Q12介绍下redis 故障转移
从节点不断探测主节点是否活着,如果认为主节点主观下线,且半数以上节点认同,就触发切换。
根据同步位置推选新主节点。
复盘:哨兵发起ping命令检测主节点,如果下线标记为主观下线,发起一轮投票,假如超过阈值,则标记为事实下线。
然后从优先级、复制进度、ID大小选择新的主节点。之后旧的主节点降级为从节点。
Q13Kafka怎么保证发送成功的
回答:消费者发送失败设置ACK为All(所有副本写入)。
复盘:
Q14 不断重试可能导致生产者发送重复消息答:消费端设置唯一业务ID去重。业务方去保证
复盘:
消费侧 新增数据库的话 唯一索引去重 ,更新的话,生成token 之后存入redis
Q15其他
会写Python,用过LangChain、Plotly、Pandas等库。
Q16如何排查服务挂掉了
Linux排查问题:先看TOP命令看CPU,再看是否死锁。用jstack打线程日志,搜Deadlock字段。先在Nacos看服务是否存活,
Q17服务响应慢如何定位?
用SkyWalking看链路哪阶段超时。
Q18kafka的重试策略?
点了?后面提示 重试次数
Q19redis的cluster中主从同步过程
点了?回家想起是ping pong机制
面试总结
感觉
问到kafka怎么解决重试问题的,不知道在问啥redis的cluster中主从同步过程,点了
寄寄寄
不足之处
Claude code 致命Threadlocal 真的记不住
查看25道真题和解析