## 1、基本情况
博主`17届双非一本毕业`, 主要是搞`Java开发`的, 没有大厂经验. `2020` 自己也马上快`3年工作经验`了. 如果再不找找机会进大厂深造一下, 后面的竞争力和个人的提升将会更难.因此在现在公司磨砺了两年之后, 开始向大厂迈进~ 这篇博客主要是想分享一下自己在面试过程中所遇到的问题,相对比较坎坷,前后经历了`3个多月`.希望大家也能在找工作的过程中,坚持下来!
## 2、面试结果
- `阿里-蚂蚁支付宝` **P6** offer
- `腾讯-pcg` **2-3** offer
- `字节` **2面** 后放弃
## 3、面试过程
### 3.1、阿里-天猫超市
#### 一面
> 1、静态代理,动态代理
简单描述区别, 然后可以引出 `jdk动态代理`和`cglib` 的底层实现原理(`Proxy` 和 `InvocationHandler`).
再引入 `Spring AOP` 在不同情况下采用的代理实现方式
最后举例项目中动态代理的**使用场景**(常见的 `日志打印`)
> 2、future (重点)
`Future`用来代表异步的结果.可以引出 `ExecutorService.submit` 和 `ExecutorService.execute` 的区别
如果有研究过一些框架的源码, 可以说一下 `Future` 在其中起的作用(**超时控制**)
![](https://user-gold-cdn.xitu.io/2020/6/5/17282a0c92c17c70?w=765&h=393&f=png&s=135703)
> 3、线程池实现方式-销毁线程
这里支持需要指出 `Executors` 和 `ThreadPoolExecutor` 之间的关系
通过设置不同的入参,实现不同的线程池. 比较有意思的 `SynchronousQueue` 实现原理可以深入学习一下
线程池回收: [传送门](https://www.zhihu.com/question/40732545)
> 4、mysql 联合索引
先介绍一下什么是 `联合索引`, 索引使用场景和失效情况, 如果了解 `索引下推` 可以说一下
引出 `联合索引` 和 `主键索引` 有什么区别. 然后可以深入对比一下 `Innodb` 和 `MYISAM` 的区别
**点睛之笔** : 自己去写几条sql 查看索引的选择规则, 你会发现并不是建立了索引就会走, 也并不是有索引下推就一定会去采用, 这就可以涉及到 `mysql 一条sql 的执行过程`
> 5、redis 集群
主要的几种集群: `主从`,`哨兵`和`redis Cluster` 这几种服务端集群. 类似 `Twemproxy` 和 `Codis`这种代理实现,如果了解可以说一下.
细问: 当前公司采用哪种方案(哨兵),为什么(数据量较少,主从+哨兵能支撑业务场景),介绍哨兵的工作原理.
**当时问了一个问题**: 如果主挂了之后,选主结束后,怎么去通知客户端. 客户端和哨兵是什么样的关系(有无关联)
> 6、mysql 分库分表
先问: 目前数据库的容量大概是多少,有没有做分库分表设计.
答曰: 目前单表数据量在`5000w `左右, 日增长在`10w以内`, 暂时没有这方面的考虑(**劣大于优**).
再引出: 分库分表有哪些方式(`垂直分库`, `垂直/水平分表`),讲解一下区别. 可以再说一下 `分布式自增id` 的实现方案,常见的比如 `雪花算法`, [美团-Leaf](https://tech.meituan.com/2019/03/07/open-source-project-leaf.html)
> 7、项目内容
```
项目介绍,主要是挖掘你在工作中的思考以及亮点. 后面统一介绍, 因为每轮面试基本都会说一次
```
#### 二面
```
二面流程比较快, 没有什么特点
```
- 介绍项目和当前公司的盈利模式
- 项目遇到最大的困难
- 项目的方案设计等
总共20多分钟, 感觉应该没什么大问题.
#### 结果
为啥那么快到结果呢, 就是凉了~
面试完没几天, 跟二面面试官沟通, 是`通过`了, 还让我准备一下后续的笔试
可能是表现稍差,对比被 ~~干掉~~ 或者 `没hc` 了
### 3.2 腾讯TEG
#### 一面
> HashMap 底层实现
介绍基本结构,对比 1.7和1.8的区别
建议深入阅读 `1.8 resize()`的源码, 还有红黑素转换的过程
> HashMap 是否线程安全,如果需要使用线程安全的呢
对比 `HashMap`,`HashTable` 和 `CurrentHashMap `的区别和使用场景
给出一 `个HashMap` 要在`线程安全`的情况下使用, 通过加`锁`和 `Collections.SynchronizedMap` 对当前 `HashMap` 进行封装
> 介绍一下红黑树
原理: [红黑树传送门](https://www.jianshu.com/p/570243549e4e)
应用场景: `JDK1.8 HashMap` , 对比 `B+树` 和 `跳跃表`
> redis 速度快是因为什么原因
- 内存
- 单线程
- 数据结构
- io多路服复用
性能瓶颈(`内存`,`网络io`), 可以指出 为解决 `网络IO` 的瓶颈,在 `redis 6.0` 提出的 单主线程,多工作线程的设计.可以对比 Memecached 的多线程模型进行对比.
> mysql 索引介绍
- 聚集索引和非聚索引的区别(InnoDb 和 MyISAM 对比)
- 索引选择(优化器怎么选择索引)
- 索引失效
- 索引下推
> 为什么选择b+树
介绍 b+树和b树的区别, 对比b+树在磁盘IO上面的优势(单页能存更多的索引),可以提一下mongodb 采用的是B树索引 .
可以参考: [为什么 MongoDB 索引选择B树,而 Mysql 选择B+树](https://zhuanlan.zhihu.com/p/102628897?utm_source=qq)
> 聚集索引和非聚集索引
参考: [聚集索引和非聚集索引 简析与对比](https://blog.csdn.net/qq_29373285/article/details/85254407)
当时踩了个坑, `聚集索引`和`聚簇索引` 其实是一个东西
> 默认主键索引
如果没有设置主键索引, `innodb` 会默认添加一个隐藏列作为主键索引
为什么需要这个隐藏列, 可以参考` innodb `的数据存储结构
如何设计主键索引: [MySQL主键设计](https://juejin.im/post/6844904132915003399)
> 虚拟内存和物理内存
参考: [虚拟内存和物理内存的理解](cnblogs.com/panchanggui/p/9288389.html)
简而言之:
```
物理内存有限, 虚拟内存通过磁盘映射的形式进行分配物理内存
从而解决多个进程同时运行的情况下内存不足的问题.
```
> 伪共享
[伪共享原理](https://www.cnblogs.com/cyfonly/p/5800758.html)
可以结合 `volatile` 和 `ConcurrenthashMap.countercell` 进行解答
> TCP如何确保可靠传输
- 数据包校验
- 重排序
- 丢弃重复数据
- 应答机制
- 超时重传
- 流量控制
> 拥塞控制
- 慢开始。
- 拥塞避免。
- 快重传。
- 快恢复
```
计算机网络这部分的内容相对来说比较考验背诵理解.
需要你用自己的语言表达出来
```
> 项目设计
```
后续补充
```
> kafka /es 有没有使用过
> 有没有了解最新版本的redis(支持多线程)
> 笔试题
笔试题的内容比较多, 有`编程题`,`算法题` 和`程序运行结果的选择题`等
#### 二面
> 项目遇到最大的问题(OOM) - 会比较长
个人的分析步骤, 感兴趣可以参考一下. 主要也是根据理论基础进行分析, 然后一步步排查.
```
1、jvm oom排查 (Java heap space)
排查过程:
1、分析oom 的原因: 主要分为内存泄漏和内存溢出
内存泄漏: 对象分配了内存, 在方法调用结束之后没有进行回收,直接进入了老年代中
内存溢出: 我们的内存容量不够,导致内存分配不足
主要从这两方面进行排查
首先排查的是内存溢出:我们机器的配置是 2核4g 的机器, 堆内存分配的是3G,按照1:2的比例进行分配
这里通过
jmap -heap 可以查看到我们的堆内存使用情况.
然后根据 jstat -gc 查看我们的gc 次数, 可以粗略的查看到我们的系统gc 情况
当时通过分析 gc.log 文件看到fgc的次数相对来说还是比较少的, 因此可以暂时排除我们内存溢出导致的oom 的可能性.
其次就是排查内存泄漏了.这里使用到了 -XX:HeapDumpOnOutOfMemoryError 命令来保存 oom 时产生的堆栈信息.
通过 MAT 工具来进行分析 内存使用情况.
当时分析看到占用比较多内存的是 java.util.map 对象比较多. 通过 MAT 工具的 leak suspects 进行分析内存泄漏可能存在的原因.
当时定位到的是我们的一个学生作业报告的接口的方法.
然后查看了一下 这个接口的调用情况,发现一天的调用量在20万次左右,平均响应时间是在400毫秒.
根据分析到的有效信息, 初步排查就是由于这个接口调用量比较多,然后导致生成比较多的一些聚合数据(主要通过map 来进行聚合), 然后由于响应时间比较长,可能会导致在ygc 的时候,根据可达性分析(gc root)判断这个对象还是存活的,然后分配到了老年代,当方法调用结束了, 就会导致这部分对象会一只存活在老年代,直到触发fgc.
如果是正常情况下, 应该会在fgc 的时候就会触发垃圾回收, 而不是发生oom. 这里是根据查看我们ygc 产生的剩余对象占用内存来进行分析的, 即如果ygc 产生了大量的存活对象,而oldgc 没有足够的内存存放这部分对象,就会导致oom.
优化过程:
1、jvm 的优化,主要有做了, 一个是增加内存,调整新生代和老年代的比例(修改成1:1),修改垃圾回收器
2、代码上面进行优化处理:
减少聚合数据对象的创建, 这个可以通过提前生成相应的报告数据
减少接口耗时
```
> 为什么要使用 redis
引入中间件都是为了解决目前存在的问题. 比如 数据库访问压力比较大, 数据存储变化频繁,数据访问频率高和数据时效性低等.
可以进一步说明,引入redis 带来的问题 和如何解决的. 比如: 引入了 redis 如何确保数据一致, redis 不可用如何保证服务可用.
> 改善后的吞吐量,数据库的qps
这里考验的是数据敏感性, 每次改动之后要求对系统进行测评. 判断这次修改是否对服务性能进行了提升,提升了多少, 哪里还有瓶颈等
> 数据库的事务, innodb 的索引实现原理
事务隔离级别 和 如何实现的.
如何实现这一块需要去了解一下 mvcc
> io多路复用
`select`、`poll` 和`epoll` 对比
有遇到深入问 `epoll` 事件通知是如何实现的.
推荐: [Linux IO模式及 select、poll、epoll详解](https://segmentfault.com/a/1190000003063859)
> 性能瓶颈,如何再优化
主要围绕这三个点进行分析:
- cpu
- 内存
- io
> rpc 调用过程, (为什么看dubbo源码)
rpc 调用过程这个问的挺多的, 可以参考 dubbo 的架构设计, 然后一步步跟着源码走一遍就理解了.
为什么看: 提高自己的编码能力和设计能力 (要带着问题去看源码, 不然很容易忘记)
> 小组内的工作职责
### 三面
> 工作内容
- 版本开发
- 问题处理
- 需求分配
- 技术评审
> 重构(思路,实现)
建议阅读: `《重构-改善既有代码的设计》`
> 性能优化做了什么
`jvm 调优` ,`sql 优化/重建索引` 和 `MQ 解耦`
> 同步和异步的区别
> Linux io多路复用/aio
参考上述 `面试二`
> linux select 通知
> B+树和红黑树
> HashMap 红黑树
> 进程间通信的方式
- 管道
- 匿名管道
- 信号
- 信号量
- 消息队列
- 共享内存
- 套接字
> 系统性能瓶颈
主要围绕这三个点进行分析:
- cpu
- 内存
- io
#### 结果
`TEG` 这边的面试, 也是`N` 了
### 3.3 腾讯PCG
#### 一面
> rocketmq 如何保证消息可靠
从生产, MQ 和消费三端进行分析
> 消息队列技术选型
对比常见的 `RabbitMQ`,`RockerMQ` 和 `Kafka` 技术特点, 结合公司的实际场景抉择。
> rocketmq half message
介绍 `half message` ,失败如何回调等
> rocketmq 消费失败
如何解决消费失败的问题,和消费失败可能导致的 `n+1` 问题
> dubbo 通信过程
`rpc `调用过程
> dubbo 本地缓存地址
`dubbo` 底层源码
> redis 集群模式
> redis 主从同步
> spring 事务传播机制
> mysql 隔离级别
> redis 跳跃表 层数的设置
上述可能有比较多重复的内容, 因此没有再做详细的介绍了, 大家可以自行再去学习一下~
#### 二面
```
二面的过程有点像聊天,面试官跟 我前面别的部门(不是上面的TEG)的面试官认识,因此了解我的整体情况。
整个面试过程有点类似指导吧,指出我的不足,然后给我一些建议。
也有问一下比较常规的问题,也是上面有提到的一些内容。
```
#### 三面
> 项目介绍
```
项目介绍主要从:
1、业务场景
2、性能数据
3、问题难点
4、性能瓶颈
这几个方面进行分析吧
```
##### 1、业务场景
博主这边做的项目是一个教育行业的系统, 主要是描述了一下 学生在线答题的业务场景。各位可以根据自己的项目进行梳理。
##### 2、性能数据
性能数据这一块应该是社招比较看重的问题, 基本每一轮面试都会有面试官问 性能怎么样, 需要我们平时对自己系统有一定的了解,并且清楚实际数据怎么样。 具体包括: 每天`访问量`,服务 `qps/tps`,用户量和机器数量(机器配置)等多方面的数据。
##### 3、问题难点
这里我主要将两个地方吧, 一个是上面说到的 oom 问题定位处理 , 一个是 RocketMQ 解耦。
上面介绍了 oom, 下面简单介绍一下结合项目引入 RocketMQ。
```
1、为什么引入RocketMQ
通过对核心接口的压测, 发现接口 tps 相对较低,经过排查发现主流程中操作步骤相对较多。
一次写请求处理了比较多内容,导致整个请求的响应缓慢。
通过将核心的流程和辅助功能进行拆分, 通过异步的方式完成后续的工作,从而提高接口的吞吐量。
问题: 响应缓慢,吞吐量低
期望: 快速响应,提高tps
解决方式: 通过引入 RocketMQ 进行异步操作/解耦
2、为什么使用RocketMQ
技术选型: RabbitMQ,RocketMQ和Kafka
主要从:消息堆积,响应速度,底层语言和使用场景进行分析
3、如何保证消息的可靠性
从 客户端,MQ和消费端来进行保证消息可靠。
客户端: 通过事务消息来进行保证,或者失败重试(sendResult判断)
MQ : 通过RocketMQ 集群,进行保证,主要由运维负责(可能会牵扯到MQ消息保存的问题)
消费端:1、消费幂等和2、流水表的形式
这个问题需要结合到项目中的实际场景进行分析, 不能硬套
4、优化后的吞吐量
这个是比较核心的问题, 你优化完之后, 没有做性能的测试,凭什么说引入就好了
(引入中间件原本就会降低系统可靠性,提高复杂度)
因此需要在优化后,进行一轮的压测(注意测试场景要保持和生产或上一次测试场景一致)和消息的消费速度(避免消费过慢导致堆积)
5、优化后的性能瓶颈在哪?
主要从: cpu,内存和IO 三方面进行分析吧, 具体系统具体分析。
```
##### 4、问题难点
cpu,内存和IO 三方面进行分析吧, 具体系统具体分析。应该没有啥系统是没有瓶颈的。
#### hr面
> 工作内容
> 团队身份
> 学习规划
> 职业规划
> 个人绩效
#### offer
千辛万苦,终获腾讯offer,上面虽然只写了两个部门的面试内容,但是我至少面了4个部门了(2个月内),所以,没什么岁月安好,只有负重前行,才能实现梦想。
### 3.3 阿里蚂蚁
#### 一面
> 1、匿名类,内部类静态内部类
> 2、HashMap 1.7和1.8区别
> 3、BlockingQueue 相关知识
> 4、线程池的创建形式,使用场景
> 5、多线程下实现一个计数器
> 6、wait 和notify
> 7、B+树和红黑树
> 8、数据库的隔离级别
> 9、数据库如何解决幻读
> 10、mysql 索引
> 11、redis 分布式锁
> 12、redis 哨兵集群
> 13、rpc 调用过程
> 14、zookeeper 是怎么服务发现的
> 15、zookeeper 心跳检测
总体来说,跟上面的面试过程也是大体上面相似,也没有什么难点的。因此也不做详细分析了~
#### 二面
二面进行的也是比较快,主要是两个问题吧
> 项目介绍
也是跟上面的差不多内容
> 场景题
用户的资源权限数据库设计
#### 三面
三面面试官问题主要是跟业务场景和架构方面的, 整体跟腾讯的三面差不多(实际上是因为忘记了问了啥, 主要也是跟项目相关的)
#### 四面
整个流程下来大概10分钟左右,当时刚面完头条,有点突然。
> 项目难点
> 问题处理
> 团队角色
> 学习方法
#### hr面
hr面一共面了10分钟左右,当时面完也是慌的一批,咋那么快呢。
问的问题主要就是:
> 离职原因
> 职业规划
> 薪资水平
#### offer
最后也是成功拿到了ali 的offer ,完成自己的理想了吧! 以后便以 `九灵` 行走江湖了~~
## 4、总结与建议
楼主在面试过程中也不是一帆风顺,也是披荆斩棘走过来的,`2020` 不是一个安稳的时间, 每天在发生在各种各样的变化。只有`坚持`,`把握`,`不放弃` 方能达到自己的目标。
加油吧,少年!
好了各位,以上就是这篇文章的全部内容了,我后面会每周都更新几篇高质量的大厂面试和常用技术栈相关的文章。感谢大伙能看到这里,如果这个文章写得还不错, 求三连!!! 创作不易,感谢各位的支持和认可,我们下篇文章见!
我是 `九灵` ,有需要交流的童鞋可以 加我wx,`Jayce-K`,关注公众号:`Java 补习课`,掌握第一手资料!
如果本篇博客有任何错误,请批评指教,不胜感激 !