转载

快手 | 资深Java架构师 | 北京 | 2019 [面试失败经验]

前景

不靠谱的推荐

面试机会是通过猎头推荐的,差不多在推荐后的3天左右快手HR联系我约定面试时间。在这之前,猎头与我进行了沟通,了解了我的基本诉求和基本情况。但是,当我收到HR面试通知的短信时,却显示着完全不匹配的职位“资深Java架构师”。对于语言方面我会多少认为快手可能会包容跨语言的情况。所以,还是准备去试试。

一面前的等待

不知道在她身上刚刚发生了什么

为了能够容易进入面试状态,我提前了20分钟到达了快手总部。前台的服务人员是一个女孩,她的态度让人感受起来极其的不舒服,不知道在她身上刚刚发生了什么,不过这不管我的事儿。但是,我还是不得不找保安再一次确认面试地点应该如何走过去。

顺利地到了面试地点所在大楼的入口,HR正在等待我。我上前简单介绍自己并确认对方是在等待我的HR。

HR居然没有我的完整简历

在HR带领我上楼的电梯中,她示意我了一张灰灰的A4纸,上面凌乱地散落了一些文字,描述的是我的基本情况。但是,不知道这是从哪里搞过来。“ 你有简历吗?我感觉这个不太好,我帮你再印一份。 ”,她说。“ 好,那我发你一份 ”,我差异地盯着那份不知道哪里导出来超级简陋简历说。

欲说又止,心里在嘀咕,估计面试官都没有认真看过简历吧。

还有一个细节,HR手上拿了一份表格,上面排得整整齐齐的面试者的资料。

技术的一面

一面的面试官是一个高高瘦瘦的男同志。看起来,属于踏实的那一种。

自我介绍

进来时,我主动站起来迎合。经过简单地寒暄,就进入了正式面试话题。首先,他要求先介绍一下我的履历。

项目介绍

在简短地介绍完履历和目前负责的项目之后,他首先是先问了一些行为问题。

有人觉得简单的业务并没有成长,所以你对业务和系统架构怎么看?

首先,我觉得业务和系统架构这并不是两个独立的事情,应该先有了业务需求,但是经过业务复杂的迭代,慢慢的简单的设计模式无法满足要求时,就会调整系统的架构设计,就形成了所谓的系统架构。所以,我觉得这是一个先有业务,在业务基础之上,才慢慢发展出系统架构的一个过程。

当然,其实在我实际的工作中,因为我的工作性质,业务更多还是写一些IF ELSE这样的简单的业务逻辑。很多同事都会抱怨说这真是太没有成长了,但是我觉得这并不能完全怪罪工作的性质。其实,我觉得有很多事情都是需要思考的。这其中简单的IF ELSE背后,如果我们面对一个问题加以思考,其实有很多有意义的事情去做,比如你可以怎么更高效的去实现它?

他点了下头,进入了下一个话题。从我之前的介绍中,引出了其中的一个项目,让我讲讲是如何做的,它的系统架构师怎么样的?

我首先讲解了项目的背景、收益、功能以及后续的复杂功能需求、系统架构时的场景假设,比如用户量,系统服务器的现状等等,接着分别以在线和离线方面讲解了项目的系统架构。最后,我又提及了前面说到的复杂功能需求是如何解决。

面试表示用过这一块产品,他就着回滚场景功能,数据一致性和单点故障问题进行了提问。在其中,因为不能透漏项目,所以就不讲述我具体是怎么回答的了。

数据一致性

数据一致性方面主要是通过版本的概念来保证,比如可以至少保留两个版本的数据,一个是老数据,一个是新修改的数据,每个数据对应一个版本,再通过Redis维护一个可用版本号。通过Redis修改版本号,来保证所有服务器读取的数据是某一个特定版本号的数据。来保证数据的一致性。此外,他提到你是否知道zk,我表示我知道,并讲述了他在Codis集群架构中的一些基本应用。同时,我也分析了这个数据一致性还是要权衡成本和需求场景,如果需求场景对于数据一致性不是敏感的,是可以容忍呢,那么可以不用考虑数据一致性的情况。

单点故障

单点故障问题我提到了可以使用热备份(hot standby),他纠正了一下应该是冷备份。

思考

在系统可用性上的考虑还是欠缺的,可以看出在面试时有些露怯。

Java数据结构实现原理

接着,面试官将话题引到Java,“既然是Java架构师,我们还是要考察对于Java语言的掌握情况”,面试官说。

请说出Java中常用的集合,并描述其继承关系,实现的算法与数据结构。

当时对于数据结构的问题还是胸有成竹的。首先,我表明自身近期没有对Java使用的过多,继承关系没有办法回答了。但是,可以说说常用的集合与其算法数据结构。

我流利的写出了几个常用数据结构:List/Map/Set/Array/Queue/Deque/PriorityQueue,同时分别简单地介绍了其算法与数据结构。

  • List 双向链表
  • Map 说是HashTable,并指出C++的map是红黑树
  • Set 想了一阵,说应该和Map一样,也是HashTable
  • Array 是一个动态数组
  • Queue FIFO 与stack对应(FILO)
  • Deque 双向队列
  • PriorityQueue 优先级队列,说是用红黑树实现(这个地方说错了,应该是近似完全二叉树)

随后,面试官说你可以指定一个你拿手的集合,讲讲其内部的原理。

我介绍了下HashTable的实现原理,并讲述了两种冲突的解决方法——拉链法与再次散列法。同时,并提及了再次散列发中的线性探测与二次探测会导致一次群集与二次群集的现象。此时,我观察面试官有些疑惑,估计他对这块也并不是很熟悉。

接着,面试官问Java中用到的是哪种冲突解决方式,我表示不了解(是拉链法)。

思考

现在看来,答得并不理想,并没有结合Java详细的阐述各个集合所用到的数据结构。比如,上面的Map和Set其实应该有相应的派生类,TreeMap、HashMap等。以及,优先级队列居然说是红黑树。但是,关于不了解Java的HashMap到底用的是哪种解决冲突的方式,我觉得这并不是太大的问题,这里面的考察点应该是数据结构,但是往往国内的企业都会过重的看重编程语言层面的理解,这一点和Amazon的区别很大(Amazon用Java的场景非常多,但是公司不会在面试时面试语言层面的知识,我理解Amazon希望考察的是一个候选人对于基础数据结构与算法的理解与掌握,因为这对于一个候选人来说最为重要,如果了解原理,可以在快速的时间内结合语言的特性快速掌握)。

线程池的管理

面试官让我结合Java场景,谈一谈如何解决线程池的管理以及用到的数据结构,并在最初提及了两个方法——submit与shutdown。

说实话,也许是我对于Java的了解甚少,现在为止我也没有理解面试官的考察点在哪里。也许,这是一个模糊的问题,更多的就是想考察候选人是否有相关经验吧。

我首先提及了线程池的优先级问题时,面试官打断提醒,线程优先级的管理操作系统会负责,我的问题并不需要考虑这些。你可以往应用层面思考一下该如何处理。

随后,我提及了之前做过的类似QQ的聊天项目,并谈到每一个客户端作为一个线程,在服务端启动了一个线程池来维护客户端的链接,使用了HashMap的数据结构,Key为userid,Value是线程实例。同时,考虑使用分布式锁来保证线程池的上限。当链接超过上线时,会直接断开请求。

思考

这块当时回答的最糟糕的一块,首先没有能够快速领会面试官的意图,导致中间与面试官进行了二次确认,并停顿了一小段时间思考。其次,好像我在回答时提及了他的问题(submit),但是没有提及(shutdown)。我想,我在线程池的管理上应该多多了解一下。

算法

他说,最后一道算法题,也许对你来说不算什么。当时,我想,他怎么对我这么有自信(哈哈)。

有20亿个正整数,数的范围在1-2^32 -1,内存是Xm(面试官居然说我不清楚具体内存应该是多少,反正就假设,如果存放这么多数字内存是不够用的。我觉得,这块面试官准备的还是欠缺,居然不提前计算好。),要求提供一个API服务,用于查询当前数字是否在集合中。

其实,这是一道系统设计的题目,设计系统需要考虑场景功能(S)、限制假设——用户规模、发展速度等(N)、架构——在线、离线(A)、数据(K)与迭代(E)等问题,面试官仅仅关心其中架构(A)中的算法实现问题罢了。

我与面试官明确了意图之后——仅关心算法实现,提及可以使用位图实现。“如何实现?“,面试官立即追问到。因为数字的范围在1-2^32-1,所以可以申请2^32个位空间来存放数据。因为我们的需求是仅仅判断是否存在某个数字,所以可以忽略重复的问题。这样空间可以减小32倍。“那如果内存还不够用呢?”,面试官追问到。可以考虑将数据的一部分存入内存,然后可以利用诸如LRU、LFU这样的缓存淘汰算法来实现缓存的管理。同时,可以采用定期与惰性两种时间机制淘汰缓存。

思考

这块的回答基本上没有漏洞,而且很顺畅,最后面试官也没有表示出追问的意愿了,应该是问到了边界。

原文  http://blog.ihuxu.com/kuaishou-senior-java-architect-beijing-2019-reject/
正文到此结束
Loading...