2019 秋招蘑菇街一面面经

这篇文章是读者「帅飞」的投稿。投稿网友给大家分享一下他的秋招提前批面试经历,目前三面技术面已过,hr 面也面过了,正在等消息。由于内容太多,先分享一面的面经。

自我介绍一下吧

面试官您好,我是 xxx 大学软件工程的一名大三学生,从大一开始学习前端,产生了对编程的兴趣,大二开始接触 Java,大二下学期学了 ssm,Spring Boot 等框架,也做了一些项目。后来发现基础很重要,于是从大三开始一直到现在,一直在对基础进行学习。比如:JVM,并发,操作系统,网络等。

看你的项目是分布式系统,那你的上游系统调用你的系统时可能会出现超时的问题,怎么处理?

在我们的系统的话,一般有监控平台,请求超时会抛出异常,会触发企业微信邮件告警,开发人员知道以后去看一下对应的日志中的异常信息。查到具体是调用哪个接口出现的问题,这个接口里是否调用外部系统,定位问题是外部的还是内部的问题。

那如果你看到的日志就是很多请求,你认为这种是什么问题,在外部系统没有问题的情况下核心线程池被打满了?

我觉得可能是有人新改了一个功能并上线,不小心写了死循环导致的 CPU 飘高。

PS:review code 的重要性

您说的线程池爆满的原因是可能一个接口中存在耗时的操作,导致请求这个接口的请求一直占用线程池,线程池被打满,从而导致后续来的其他接口的请求也会被影响。

这种情况一般可以服务降级、限流来处理。

在外部流量没有暴增的情况下,如果你的服务每隔半个小时会出现服务不可用的情况,这种怎么排查?

它这个是突然每隔半个小时还是其他情况?

就是这一天 11 点出现了,以后每隔半小时就会有两分不可用,qps 都保持正常值

我猜这种情况一般出现在,定时任务同步一些数据到其他系统,由于网络的问题,那边服务慢的话就会导致一个超时,然后就会发生这个问题。

常接受请求,也没有任务跑,你会往哪个方面想?

那它会不会受到部署机器其他服务的影响呢。

没有

想了几分钟…..,这个目前还想不到其他的。

我可以给你个提示,往内存方面想

昂,立马 get 到点,是可能存在内存泄露吗?是不是由于存在内存泄露导致 full gc,gc 太频繁导致的。

对,那这种问题怎么排查解决

如果内存溢出的话,一般可能会有 OOM 抛出,JVM 可以设置参数在出现 OOM 时 dump 下内存的镜像,然后你可以利用一些分析工具,分析这个 dump 文件,有的工具直接可以给你一些优化建议,或者你可以找到哪个类的内存使用情况,找到内存泄露的点,去看代码。一般是 NIO 引起的,因为 Java 8 开启方法区使用的是元空间,不是永久代了。元空间是本地内存,不是堆内存,不受 JVM 管理,由操作系统管理,所以使用不当可能会出现内存泄露的问题。

好,那下一个问题,你那边用的是 dubbo 把

是借鉴 dubbo 开发的一个 rpc 框架吧

正常 Java 用的是 dubbo,之前是 php,为了 php 和 java 微服务之间的跨语言调用,实现了一个跨语言的 rpc,现在已经全部转为 Java 了,都用 dubbo 调用。而且微服务架构方面又做了改进,使用了 Service Mesh,面向云原生。

dubbo 服务的启动、注册流程,说一下

首先,有个服务的提供者启动起来后,会先向服务注册中心注册服务,如果是 zk 的话,它就是在某个 dubbo 的目录**册上下,其他消费者想调用的话,就从 zk 上把对应的提供者的 ip 地址啥的拉下来缓存起来。然后就可以调用了。

那提供服务的提供者 ip 更改了,消费者是如何动态感知服务提供者的改变呢

一般分布式注册服务可以动态感知。如果是 zk 的话,服务提供者在 zk 上注册服务时创建的是临时节点,如果服务 ip 更改了或者服务挂了,服务的调用者通过 zk 的 watch 机制可以监听到服务提供者目录下的节点增加、删除、修改事件。

你用到了很多队列,kafka、rabbitmq 了解吗

我现在这边用的是 nsq 和 kafka,kafka 一般是大数据那边离线处理一些东西,nsq 一般是告警信息,两个系统之间进行解耦,进行信息交互时,发消息到 nsq。区别的话,kafka 对大数据处理能力比较好,nsq 的话一般作为一个正常的消息队列,同步改异步就可以用 nsq。

既然 Kafka 可以处理大数据,那为什么不用 kafka,而用 nsq 呢?

这个问题我之前想过,问过我的 leader。kafka 一般是大数据那边流处理什么的,它那边一般都只接受 kafka 的消息,和大数据集成比较好。至于选 nsq 的话,它是结合当时的业务场景选择的,这个也没有选哪个好哪个坏。

那他当时选型的时候,为什么不用 kafka

因为 kafka 貌似对于延时消息等支持的不太好,事务这些,它虽然对大数据的处理的好,但是它也有缺漏的地方,它有它的专攻方向,比如:吞吐量方面,但是也有它的不足之处,就好比计算机中的摩尔定律。一般业务系统常需要一些延时消息就需要用 nsq 了。

根据我的项目问的一些问题

……

有数据库调优经验吗?对于数据库有多索引匹配时,有什么经验吗

这个匹配的话,比如:ABC 三个组合索引,必须要顺序执行,比如 A = 2,C =2 。这个时候就不会执行,因为它破坏了顺序性。

你说这种情况是完全用不到吗

是的,因为它不满足索引的最左匹配原则。

那比如说,我数据库有多个索引,A,B,BC,一个查询条件 A,B,C 都有,那一般怎么查看呢

这个一般的话是用 explain 去分析一下 sql 的执行计划,它会输出可能走的索引,真正走的索引,扫描的行数,额外的消耗(extra),用没用临时表等。

那它分析出来的索引就是数据库一定会用的索引吗

explain 分析出来的吗

或者说,你觉得它 explain 分析出来的就是最佳的索引吗

一般情况下最佳的,数据库会根据你的 sql,通过解析器生成对应的语法分析树,它对这个树进行一些规则的优化后,会生成一些查询计划,通过基于时间成本的分析算法选出一个尽可能是最佳的查询计划。这个具体合不合适很难说。

你没有遇到建的索引不好,导致走的索引是最差的情况吗

这个一般的话,可能是你对索引一无所知,导致一些索引的规则不去遵守,而且数据库索引的匹配规则很多,很容易走坑。如果你的业务一定要走你设置的那个索引,mysql 也可以通过设置强制走你设置的某个索引。

你对 Java8 了解吗

了解,因为我现在参与的项目就大量用了 Java8 的特性。比如:stream,lambda 表达式,时间 API 等。具体应用场景的话,比如你一个接口要返回 VO List 集合,而你数据库查出来的是 DO List 集合,这个时候你就可以用集合的 stream 去做这个转换。相比于传统的写法,代码会变的很简单和清爽。

流式编写代码的好处和坏处可以说一下嘛

好处的话,写代码的效率快了,看着很舒服。

坏处的话,流式性能不怎么好,并发情况很多的情况下才体现出好。

我觉得最主要的是,之前你自己写的话,就面向过程化了。流式的话,Java8 提倡的是面向函数式编程嘛。编程模型之前最开始是面向过程,然后面向对象,面向元编程,面向切面编程,面向函数式编程,以后 java9 的面向模块化编程。而且把过程封装在函数中,通过函数去转换数据的状态对于线程安全方面也有很大的好处。

如果数据库对一些记录存在热点更新操作,有大量的更新,怎么解决呢

一般可以利用多级缓存去解决。如果数据量太猛增的话,你用 redis 客户端访问 redis 服务端都访问不到,因为带宽被打满了嘛。这种情况可以提前去探测某个 key 是不是热点,然后在本地缓存操作。

你怎么即时同步数据给其他人呢

它会有一个算法提前探测某个 key 是否是热点,然后框架会帮你进行本地缓存的管理。

数据库有单热点,那你怎么解决

这种一般先做一个缓存,然后可以用消息队列削峰填谷。

操作缓存可能会超时,你怎么保证这个数据的正确性呢?因为你加了缓存呀

对对,这个数据库和缓存保持一致性比较难保证。而且大量数据访问更新,也不能加锁,因为数据库通过行锁保证线程并发安全问题。

我要你解决的就是行锁等待导致的性能被拉低的问题,用缓存也是可以的,但是不能保证 100% 的数据一致性,那我的业务场景就是想要 100% 的数据一致性,你现在有大概的解决思路吗

这个可以用多套数据库主从集群来解决吗?通过这种方式来提升数据库的写性能。让多个集群去抗。数据库中间件可以把流量分散到各个主从集群中的主库上。

可以,这算是一种解决方案,那还有其他办法吗

修改数据库隔离级别也不行,因为它并发写的时候就会加行锁。

你打破这个行锁就行了

…… 我再想想。这个 ……

主要是单条记录引起的,它就是频繁更新引起的。

昂,这个是不是可以……… 我看 JDK 源码,频繁更新它一般是:HashMap 是非线程安全的,后来出现了线程安全版的 HashTable,但是它性能比较差,因为它直接就对整个 hash 表进行了加锁。后来出现了 CurrentHashMap,出现了分段锁,降低了锁的粒度,其实就是一种思想,你对一个热点数据的访问的话,就是分而治之,多去搞几个,均摊一下。难道是利用 hash 一致性算法把这些写请求,多分几张表。

差不多吧,思想就是分而治之,只要把单点数据拆分掉,让它变成多条数据,然后去更新多条数据,最后再合成一条。

嗯嗯。现在大数据一般也这样,大的搞不动就拆分。

从和你的对话来看,我觉得你基础也不错,基础我就不问了,我这边没有什么问题了,我看你这边,实习经历丰富,offer 收的也挺多。你有什么想问的

贵公司的技术栈,还有如果我进去以后所在的产品线。

面试官讲述了他们公司的技术栈和一些业务

面试官对我的一些职业规划的建议

多锻炼自己的技术思维 + 业务思维,可以往业务中台方向走。更好的支持别人的业务,技术主要服务于技术,要培养业务架构思维。

总结

我觉得面试过程中要避免自己一直在说,可以多和面试官去互动,去问面试官是不是这样子,这样可以避免你理解错面试官的问题。我们的项目可能大部分是 CRUD,但是我们的思维不可以停留在 CRUD,多去结合业务,也就是结合场景去思考你项目,这可能是一个很大的优势。毕竟技术是用于服务业务,去解决业务需求。

整理面经不易,花了我周末大部分的时间,如果觉得写的好话,欢迎关注公众号、转发,你们的支持是我继续写后续面经的动力。

如果喜欢本篇文章,欢迎转发、点赞。关注订阅号「Web项目聚集地」,回复「进群」即进入咱自己的技术交流群。

推荐阅读
1. 
2. 
3. 
4. 
5. 
6. 
2019 秋招蘑菇街一面面经
喜欢文章,点个在看 2019 秋招蘑菇街一面面经