Object's Blog

记一次惨烈的阿里秋招面试经验

字数统计: 2.3k阅读时长: 8 min
2019/08/16 分享

今天刚经历了一波阿里某部门的Java技术面,内心是崩溃的。本以为校招的难度可以低一点,结果面试官把我问到怀疑人生……

自我介绍

经历过面试的同学们都知道,一面的第一个主题永远是自我介绍,按照套路来呗。

我叫XXXX我来自XXXXXX大学,我今天要面试的是贵公司的
Java开发工程师,我平时主要掌握的编程语言是Java,能够
熟练使用Java进行开发,可以熟练使用Spring、SpringMVC、
MyBatis等各种常用开发框架。

面试官:沉默五秒钟…

技术面开始

面试官:好的,我们简单聊聊,我看你的简历上有两个项目,挑一个能体现你水平的跟我说一说吧。

我:好的,那我就跟你说一下我的XX项目吧,它用的主要的技术栈是巴拉巴拉巴拉巴拉…省略300字

面试官:好的,你在项目中遇到的最大的困难是什么,你是怎么解决的。

我:巴拉巴拉巴拉巴拉….结结巴巴地答完。

面试官:嗯…我看你在项目中用的数据库是MySQL,你能跟我说说MySQL的原理吗?

我:????????

上来就问原理,我是一脸懵逼的

我:不太知道….

这篇文章应该说的很完整了,太长了就不贴了:深入理解MySQL底层实现

面试官:嗯…没事,可能我这么问太宽泛了,那我问你个具体的吧,MySQL数据库中的索引是怎么实现的

我:MySQL的索引是基于B+树实现的,我举个例子吧,假设没有索引,我们在数据库中取数,就需要逐行遍历整张表,假设我有几万、几十万条数据,那么效率就会非常低,B+树索引就可以提高效率,假设我需要找15这个数,根节点的第一个指针指向1-10,第二个指针指向10-20,第三个指针指向20-30,
那我就可以通过这个索引,找到15是在第二个指针的区间,然后到达下一个节点,下一个节点的指针又是P1:11-13 P2:14-17 P3:18-20,那我就可以找到15在P2区间,这样在超大数据量环境下可以提高存取效率。
(回来写博客整理了一下语言,面试时比较紧张,答的并没有这么清楚)

面试官:好的,那你了解过什么是聚簇索引和非聚簇索引吗?

我:不太了解。(渐渐崩溃,这题没答出来挺不应该,回来一查才知道,我知道这个概念但是不知道这个名字,血亏)

聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据
非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因
出处:聚簇索引和非聚簇索引

面试官:我看你的项目中用到了redis,你能给我说说redis的原理吗?

我:(mmp又是原理…) redis是NoSQL数据库,我们平时用的MySQL、Oracle都统称为关系型数据库,这种数据库的单秒存取次数远不如redis,我知道redis是靠键值对存储的,直接在内存中存储,所以它的读取速度和写入速度可以非常快…..

我是真不知道redis的实现原理啊….把自己了解的都先说了吧。

答案:Redis核心原理 - 简书

面试官:你了解过redis的两种存储方式吗

我:RDB和AOF,RDB就是将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次的持久化文件,达到数据恢复。AOF就是将执行过的指令记录下来,数据恢复时按照顺序执行一遍,实现数据恢复。

AOF(append-only file)
快照功能并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化,将修改的每一条指令记录进文件
你可以通过修改配置文件来打开 AOF 功能:
appendonly yes
开启后,每当 Redis 执行一个改变数据集的命令时(比如SET), 这个命令就会被追加到 AOF 文件的末尾。
这样的话, 当 Redis 重新启时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。
你可以配置 Redis 多久才将数据fsync到磁盘一次。
出处:redis核心原理

RDB快照(snapshot)
在默认情况下, Redis 将内存数据库快照保存在名字为dump.rdb的二进制文件中。
你可以对 Redis 进行设置, 让它在N秒内数据集至少有M个改动这一条件被满足时, 自动保存一次数据集。
比如说, 以下设置会让 Redis 在满足60秒内有至少有1000个键被改动”这一条件时, 自动保存一次数据集:
出处:redis核心原理

面试官:问你个基础的吧,数据结构学过吧,跟我说说堆排序的执行过程吧。

我:巴拉巴拉巴拉巴拉巴拉巴拉,这样就完成了堆排序。
这题没啥说的,就挺基础的题,面试官可能已经不想问了吧。

面试官:你能跟我说说Java并发包中的ConcurrentHashMap的实现原理吗?

我:(终于问到Java的题了…) ConcurrentHashMap是Java并发包中对解决HashMap线程不安全和HashTable效率低而设计的。我先跟你说说HashMap和HashTable吧,HashMap是线程不安全的,而HashTable是线程安全的,但是HashTable的线程安全是基于在HashMap上加了synchronize关键字实现的,所以这样严重影响了存取的效率,只有一个线程能够访问到表,而其它线程就必须等待,这就变成了串行化的一个过程,效率极低,而HashMap效率高可又不能保证线程安全,所以ConcurrentHashMap就应运而生了,它底层采用分段锁,是由Segment和HashEntry实现的,Segment中含有HashEntry,当多个线程访问不同的Segment时,并不会产生冲突,只有当多个线程同时访问一个Segment时才会有争夺锁的现象发生,所以这种分段锁的设计是非常节约资源并且提高了效率。

(我觉得这题我答的还不错,当然这是本次面试的唯一一道Java题,我已经渐渐忘了我是面Java开发的了)

面试官:好的,那你知道Java1.7和Java1.8中ConcurrentHashMap有什么区别吗?

我:(…这个我还真没好好地了解过,先说HashMap吧,会一点是一点) 我先说HashMap吧,HashMap在Java1.7中采用数组+链表的方式存储键值对,当产生哈希冲突时,就将该键值对保存在链表的头部,这样就会有一种极端情况,假设一直产生哈希冲突,那么这个链表将越来越长,我们查询某个数也就无法达到O(1)的效果,由于这个原因,Java1.8中将HashMap做了修改,当单个桶元素超过8时,将链表转换为红黑树,这样就不会再出现需要遍历链表的情况,提高了读取效率。

(显然没有糊弄过去,他后来还是问了ConcurrentHashMap)

1.8中的原理和实现
数据结构
JDK1.8的实现已经摒弃了Segment的概念,而是直接用Node数组+链表+红黑树的数据结构来实现,并发控制使用Synchronized和CAS来操作,整个看起来就像是优化过且线程安全的HashMap,虽然在JDK1.8中还能看到Segment的数据结构,但是已经简化了属性,只是为了兼容旧版本
1.8中ConcurrentHashMap
出处:ConcurrentHashMap1.7和1.8的底层不同实现

面试官:好的,今天咱就到这吧,我的问题问完了,你保持手机畅通,后续如果有机会会再联系你的。

我:好的,辛苦您了。

结语

一面聊了半个小时左右,说实话听到第一个问题的时候就觉得要凉了,复习了很久的Java各种技术,结果都没有考到,Spring一句也没问,感觉挺失落的。但是还是要接着学习接着准备啊,今后的侧重点不应该全放在Java语言本身了,数据库、缓存、数据结构算法都很重要,一次面试就得长一次经验。心态还是要放平。

欢迎大家访问我的个人博客:Object’s Blog

原文作者:Object

原文链接:http://blog.objectspace.cn/2019/08/16/记一次惨烈的阿里秋招面试经历/

发表日期:2019 August 16th, 11:48:47 pm

更新日期:2019 August 24th, 3:57:08 pm

版权声明:未经作者授权请勿转载

目录
  1. 1. 自我介绍
  2. 2. 技术面开始
  3. 3. 结语