【原创】Bigo的Java面试,我挂在了第三轮技术面上.........
本文是鄙人薛某的投稿(博客主页:https://www.cnblogs.com/yeya/)。虽然面试最后挂了,但是老哥本身还是挺优秀的,而且通过这次面试学到了很多东西,我想这就足够了!加油!不要畏惧面试失败,好好修炼自己,多准备一下,后面一定会找到让自己满意的工作。相信老哥总结的这篇文章对大部分人都会有一点帮助!
下面问题的很多答案在笔主开源的 https://github.com/Snailclimb/JavaGuide (【Java 学习+面试指南】 一份涵盖大部分 Java 程序员所需要掌握的核心知识 )都有,强烈推荐各位小伙伴阅读一下。
背景
前段时间家里出了点事,辞职回家待了一段时间,处理完老家的事情后就回到广州这边继续找工作,大概是国庆前几天我去面试了一家叫做 Bigo(YY 的子公司),面试的职位是面向 3-5 年的 Java 开发,最终自己倒在了第三轮的技术面上。虽然有些遗憾和泄气,但想着还是写篇博客来记录一下自己的面试过程好了,也算是对广大程序员同胞们的分享,希望对你们以后的学习和面试能有所帮助。
个人情况
先说下 LZ 的个人情况。
17 年毕业,二本,目前位于广州,是一个非常普通的 Java 开发程序员,算起来有两年多的开发经验。
其实这个阶段有点尴尬,高不成低不就,比初级程序员稍微好点,但也达不到高级的程度。加上现如今 IT 行业接近饱和,很多岗位都是要求至少 3-5 年以上开发经验,所以对于两年左右开发经验的需求其实是比较小的,这点在 LZ 找工作的过程中深有体会。最可悲的是,今年的大环境不好,很多公司不断的在裁员,更别说招人了,残酷的形势对于求职者来说更是雪上加霜,相信很多求职的同学也有所体会。所以,不到万不得已的情况下,建议不要裸辞!
Bigo 面试
面试岗位:Java 后台开发
经验要求:3-5 年
由于是国庆前去面试 Bigo 的,到现在也有一个多月的时间了,虽然仍有印象,但也有不少面试题忘了,所以我只能尽量按照自己的回忆来描述面试的过程,不明白之处还请见谅!
一面(微信电话面)
bigo 的第一面是微信电话面试,本来是想直接电话面,但面试官说需要手写算法题,就改成微信电话面。
自我介绍 先了解一下 Java 基础吧,什么是内存泄漏和内存溢出?(溢出是指创建太多对象导致内存空间不足,泄漏是无用对象没有回收) JVM 怎么判断对象是无用对象?(根搜索算法,从 GC Root 出发,对象没有引用,就判定为无用对象) 根搜索算法中的根节点可以是哪些对象?(类对象,虚拟机栈的对象,常量引用的对象) 重载和重写的区别?(重载发生在同个类,方法名相同,参数列表不同;重写是父子类之间的行为,方法名好参数列表都相同,方法体内的程序不同) 重写有什么限制没有? Java 有哪些同步工具?(synchronized 和 Lock) 这两者有什么区别? ArrayList 和 LinkedList 的区别?(ArrayList 基于数组,搜索快,增删元素慢,LinkedList 基于链表,增删快,搜索因为要遍历元素所以效率低) 这两种集合哪个比较占内存?(看情况的,ArrayList 如果有扩容并且元素没占满数组的话,浪费的内存空间也是比较多的,但一般情况下,LinkedList 占用的内存会相对多点,因为每个元素都包含了指向前后节点的指针) 说一下 HashMap 的底层结构(数组 + 链表,链表过长变成红黑树) HashMap 为什么线程不安全,1.7 版本之前 HashMap 有什么问题(扩容时多线程操作可能会导致链表成环的出现,然后调用 get 方法会死循环) 了解 ConcurrentHashMap 吗?说一下它为什么能线程安全(用了分段锁) 哪些方法需要锁住整个集合的?(读取 size 的时候) 看你简历写着你了解 RPC 啊,那你说下 RPC 的整个过程?(从客户端发起请求,到 socket 传输,然后服务端处理消息,以及怎么序列化之类的都大概讲了一下) 服务端获取客户端要调用的接口信息后,怎么找到对应的实现类的?(反射 + 注解吧,这里也不是很懂) dubbo 的负载均衡有几种算法?(随机,轮询,最少活跃请求数,一致性 hash) 你说的最少活跃数算法是怎么回事?(服务提供者有一个计数器,记录当前同时请求个数,值越小说明该服务器负载越小,路由器会优先选择该服务器) 服务端怎么知道客户端要调用的算法的?(socket 传递消息过来的时候会把算法策略传递给服务端) 你用过 redis 做分布式锁是吧,你们是自己写的工具类吗?(不是,我们用 redission 做分布式锁) 线程拿到 key 后是怎么保证不死锁的呢?(给这个 key 加上一个过期时间) 如果这个过期时间到了,但是业务程序还没处理完,该怎么办?(额......可以在业务逻辑上保证幂等性吧) 那如果多个业务都用到分布式锁的话,每个业务都要保证幂等性了,有没有更好的方法?(额......思考了下暂时没有头绪,面试官就说那先跳过吧。事后我了解到 redission 本身是有个看门狗的监控线程的,如果检测到 key 被持有的话就会再次重置过期时间) 你那边有纸和笔吧,写一道算法,用两个栈模拟一个队列的入队和出队。(因为之前复习的时候对这道题有印象,写的时候也比较快,大概是用了五分钟,然后就拍成图片发给了面试官,对方看完后表示没问题就结束了面试。)
第一面问的不算难,问题也都是偏基础之类的,虽然答得不算完美,但过程还是比较顺利的。几天之后,Bigo 的 hr 就邀请我去他们公司参加现场面试。
二面
到 Bigo 公司后,一位 hr 小姐姐招待我到了一个会议室,等了大概半个小时,一位中年男子走了进来,非常的客气,说不好意思让我等那么久了,并且介绍了自己是技术经理,然后就开始了我们的交谈。
依照惯例,让我简单做下自我介绍,这个过程他也在边看我的简历。 说下你最熟悉的项目吧。(我就拿我上家公司最近做的一个电商项目开始介绍,从简单的项目描述,到项目的主要功能,以及我主要负责的功能模块,吧啦吧啦..............) 你对这个项目这么熟悉,那你根据你的理解画一下你的项目架构图,还有说下你具体参与了哪部分。(这个题目还是比较麻烦的,毕竟我当时离职的时间也挺长了,对这个项目的架构也是有些模糊。当然,最后还是硬着头皮还是画了个大概,从前端开始访问,然后通过 nginx 网关层,最后到具体的服务等等,并且把自己参与的服务模块也标示了出来) 你的项目用到了 Spring Cloud GateWay,既然你已经有 nginx 做网关了,为什么还要用 gateWay 呢?(nginx 是做负载均衡,还有针对客户端的访问做网关用的,gateWay 是接入业务层做的网关,而且还整合了熔断器 Hystrix) 熔断器 Hystrix 最主要的作用是什么?(防止服务调用失败导致的服务雪崩,能降级) 你的项目用到了 redis,你们的 redis 是怎么部署的?(额。。。。好像是哨兵模式部署的吧。) 说一下你对哨兵模式的理解?(我对哨兵模式了解的不多,就大概说了下 Sentinel 监控之类的,还有类似 ping 命令的心跳机制,以及怎么判断一个 master 是下线之类。。。。。) 那你们为什么要用哨兵模式呢?怎么不用集群的方式部署呢?一开始 get 不到他的点,就说哨兵本身就是多实例部署的,他解释了一下,说的是 redis-cluster 的部署方案。(额......redis 的环境搭建有专门的运维人员部署的,应该是优先考虑高可用吧..........开始有点心慌了,因为我也不知道为什么) 哦,那你是觉得集群没有办法实现高可用吗?(不....不是啊,只是觉得哨兵模式可能比较保证主从复制安全性吧........我也不知道自己在说什么) 集群也是能保证高可用的,你知道它又是怎么保证主从一致性的吗?(好吧,这里真的不知道了,只能跳过) 你肯定有微信吧,如果让你来设计微信朋友圈的话,你会怎么设计它的属性成员呢?(嗯......需要有用户表,朋友圈的表,好友表之类的吧) 嗯,好,你也知道微信用户有接近 10 亿之多,那肯定要涉及到分库分表,如果是你的话,怎么设计分库分表呢?(这个问题考察的点比较大,我答的其实一般,而且这个过程面试官还不断的进行连环炮发问,导致这个话题说了有将近 20 分钟,限于篇幅,这里就不再详述了) 这边差不多了,最后你写一道算法吧,有一组未排序的整形数组,你设计一个算法,对数组的元素两两配对,然后输出最大的绝对值差和最小的绝对值差的"对数"。(听到这道题,我第一想法就是用 HashMap 来保存,key 是两个元素的绝对值差,value 是配对的数量,如果有相同的就加 1,没有就赋值为 1,然后最后对 map 做排序,输出最大和最小的 value 值,写完后面试官说结果虽然是正确的,但是不够效率,因为遍历的时间复杂度成了 O(n^2),然后提醒了我往排序这方面想。我灵机一动,可以先对数组做排序,然后首元素与第二个元素做绝对值差,记为 num,然后首元素循环和后面的元素做计算,直到绝对值差不等于 num 位置,这样效率比起 O(n^2)快多了。)
面试完后,技术官就问我有什么要问他的,我就针对这个岗位的职责和项目所用的技术栈做了询问,然后就让我先等下,等他去通知三面的技术官。说实话,二面给我的感觉是最舒服的,因为面试官很亲切,面试的过程一直积极的引导我,而且在职业规划方面给了我很多的建议,让我受益匪浅,虽然面试时间有一个半小时,但却丝毫不觉得长,整个面试过程聊得挺舒服的,不过因为时间比较久了,很多问题我也记不清了。
三面
二面结束后半个小时,三面的技术面试官就开始进来了,从他的额头发量分布情况就能猜想是个大牛,人狠话不多,坐下后也没让我做自我介绍,直接开问,整个过程我答的也不好,而且面试官的问题表述有些不太清晰,经常需要跟他重复确认清楚。
对事务了解吗?说一下事务的隔离级别有哪些(我以比较了解的 Spring 来说,把 Spring 的四种事务隔离级别都叙述了一遍)
你做过电商,那应该知道下单的时候需要减库存对吧,假设现在有两个服务 A 和 B,分别操作订单和库存表,A 保存订单后,调用 B 减库存的时候失败了,这个时候 A 也要回滚,这个事务要怎么设计?(B 服务的减库存方法不抛异常,由调用方也就是 A 服务来抛异常)
了解过读写分离吗?(额。。。大概了解一点,就是写的时候进主库,读的时候读从库)
你说读的时候读从库,现在假设有一张表 User 做了读写分离,然后有个线程在一个事务范围内对 User 表先做了写的处理,然后又做了读的处理,这时候数据还没同步到从库,怎么保证读的时候能读到最新的数据呢?(听完顿时有点懵圈,一时间答不上来,后来面试官说想办法保证一个事务中读写都是同一个库才行)
你的项目里用到了 rabbitmq,那你说下 mq 的消费端是怎么处理的?(就是消费端接收到消息之后,会先把消息存到数据库中,然后再从数据库中定时跑消息)
也就是说你的 mq 是先保存到数据库中,然后业务逻辑就是从 mq 中读取消息然后再处理的是吧?(是的)
那你的消息是唯一的吗?(是的,用了唯一约束)
你怎么保证消息一定能被消费?或者说怎么保证一定能存到数据库中?(这里开始慌了,因为 mq 接入那一块我只是看过部分逻辑,但没有亲自参与,凭着自己对 mq 的了解就答道,应该是靠 rabbitmq 的 ack 确认机制)
好,那你整理一下你的消费端的整个处理逻辑流程,然后说说你的 ack 是在哪里返回的(听到这里我的心凉了一截,mq 接入这部分我确实没有参与,硬着头皮按照自己的理解画了一下流程,但其实漏洞百出)
按照你这样画的话,如果数据库突然宕机,你的消息该怎么确认已经接收?(额.....那发送消息的时候就存放消息可以吧.........回答的时候心里千万只草泥马路过........行了吧,没玩没了了。)
那如果发送端的服务是多台部署呢?你保存消息的时候数据库就一直报唯一性的错误?(好吧,你赢了。。。最后硬是憋出了一句,您说的是,这样设计确实不好。。。。)
算了,跳过吧,现在你来设计一个 map,然后有两个线程对这个 map 进行操作,主线程高速增加和删除 map 的元素,然后有个异步线程定时去删除 map 中主线程 5 秒内没有删除的数据,你会怎么设计?
(这道题我答得并不好,做了下简单的思考就说可以把 map 的 key 加上时间戳的标志,遍历的时候发现小于当前时间戳 5 秒前的元素就进行删除,面试官对这样的回答明显不太满意,说这样遍历会影响效率,ps:对这道题,大佬们如果有什么高见可以在评论区说下!)
......还有其他问题,但我只记住了这么多,就这样吧。
面完最后一道题后,面试官就表示这次面试过程结束了,让我回去等消息。听到这里,我知道基本上算是宣告结果了。回想起来,自己这一轮面试确实表现的很一般,加上时间拖得很长,从当天的 2 点半一直面试到 6 点多,精神上也尽显疲态。果然,几天之后,hr 微信通知了我,说我第三轮技术面试没有通过,这一次面试以失败告终。
总结
以上就是面试的大概过程,不得不说,大厂的面试还是非常有技术水平的,这个过程中我学到了很多,这里分享下个人的一些心得:
1、基础!基础!基础!重要的事情说三遍,无论是什么阶段的程序员,基础都是最重要的。每个公司的面试一定会涉及到基础知识的提问,如果你的基础不扎实,往往第一面就可能被淘汰。
2、简历需要适当的包装。老实说,我的简历肯定是经过包装的,这也是我的工作年限不够,但却能获取 Bigo 面试机会的重要原因,所以适当的包装一下简历很有必要,不过切记一点,就是不能脱离现实,比如明明只有两年经验,却硬是写到三年。小厂还可能蒙混过关,但大厂基本很难,因为很多公司会在入职前做背景调查。
3、要对简历上的技术点很熟悉。简历包装可以,但一定要对简历上的技术点很熟悉,比如只是简单写过 rabbitmq 的 demo 的话,就不要写“熟悉”等字眼,因为很多的面试官会针对一个技能点问的很深入,像连环炮一样的深耕你对这个技能点的理解程度。
4、简历上的项目要非常熟悉。一般我们写简历都是需要对自己的项目做一定程序的包装和美化,项目写得好能给简历加很多分。但一定要对项目非常的熟悉,不熟悉的模块最好不要写上去。笔者这次就吃了大亏,我的简历上有个电商项目就写到了用 rabbitmq 处理下单,虽然稍微了解过那部分下单的处理逻辑,但由于没有亲自参与就没有做深入的了解,面试时在这一块内容上被 Bigo 三面的面试官逼得最后哑口无言。
5、提升自己的架构思维。对于初中级程序员来说,日常的工作就是基本的增删改查,把功能实现就完事了,这种思维不能说不好,只是想更上一层楼的话,业务时间需要提升下自己的架构思维能力,比如说如果让你接手一个项目的话,你会怎么考虑设计这个项目,从整体架构,到引入一些组件,再到设计具体的业务服务,这些都是设计一个项目必须要考虑的环节,对于提升我们的架构思维是一种很好的锻炼,这也是很多大厂面试高级程序员时的重要考察部分。
6、不要裸辞。这也是我最朴实的建议了,大环境不好,且行且珍惜吧,唉~~~~
总的来说,这次面试 Bigo 还是收获颇丰的,虽然有点遗憾,但也没什么后悔的,毕竟自己面试之前也是准备的很充分了,有些题目答得不好说明我还有很多技术盲区,不懂就是不懂,再这么吹也吹不出来。这也算是给我提了个醒,你还嫩着呢,好好修炼内功吧,毕竟菜可是原罪啊。
推荐阅读
新手也能看懂的 SpringBoot 异步编程指南
如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。
欢迎关注