头条终面:写个消息中间件

每一个时代,都不会亏待会学习的人。java

你们好,我是 yes。web

这种设计类问题想必你们都不陌生,面试时或多或少都能碰到。面试

好比如何写一个线程池?如何写一个 HashMap ?如何写一个 RPC 框架等等,固然这里的写不是真的叫你用代码写出来,只是说说设计理念,总体架构。算法

这个面试题来自于一个读者的字节面试经历,我会从面试技巧和消息中间件的设计两个方面阐述。安全

我以为重点在于面试技巧,由于它通用。微信

两种极端的状况

大多数同窗遇到这种问题会出现两种极端的状况:架构

  • 第一种:一脸懵逼,两眼无神,不知从何提及,万般思绪,都化做一声叹息。框架

  • 第二种:夸夸其谈,像是口中架起了一把加特林,哒哒哒哒哒哒哒哒,还冒着蓝火。异步

第一种不用说了,好一点的面试官可能会引导你,会问一些提示性的问题,一步一步地带你渐入佳境,固然你要是胸中无点滴,那仍是没救的,场面就异常地尴尬。编辑器

第二种会把面试官整蒙了,或许你真的懂不少,不少细节也都清晰,可是你不能一古脑儿的都抛出来,这会显得你抓不住重点。

面试官也是人

这点其实很关键,不少把面试官当成一个莫得感情的提问机器人,以为他无所不能能够彻底 get 到你的点,却不知你引觉得傲的细节回答,他可能以为你在说蛇皮。

是人就会有感情,就须要交流,好的面试官会把控总体进度,从拉家常开始,让场子热起来再一步一步的深挖。

固然也有一些面试官比较弱,这时候就须要你来特地地流出一点空白,来让面试官涂鸦,让面试官感受你这人就很舒服,你这波就稳了。

固然即便面对着把控全场的面试官你也得主动出击,每一个人都有本身的擅长点,你须要引导面试官来询问你的长处。

正确的回答姿式

正确的回答姿式是 BFS(广度优先搜索) 而不是 DFS (深度优先搜索),什么意思呢?

就是咱们须要先从大局上讲出须要设计的东西的重点,而后再等待面试官的继续提问,深挖

咱们须要揣摩面试官的心理,从他的提问能够看出他想要知道的重点是哪一个方向的。

好比就拿 HashMap 来讲,你简单的把获取、写入、冲突处理、扩容啥的都说了,而后等待面试官接下来的提问,有可能会往线程安全方面深刻,也有可能会往扩容方向再挖,好比引出 Redis 的 hash 扩容等等。

因此说给面试官留提问的机会,抓住他的喜爱或者说熟知的方向回答,这样若是你答得好,相互之间谈的来,面试官会对你高度承认。

并且在说各设计要点的时候也要注意停顿,要留机会给面试官插话,让面试官充分参与你的设计

仍是拿 HashMap 做为例子,好比你说了获取、写入、冲突以后稍做停顿,这时候大几率面试官还会问还有吗?让面试官有参与感,让他感受通过他的引导这个设计才逐步地完善

固然若是不问也没事,你停顿下继续说就行。

让面试成为一场技术交流,这是面试的最高境界,相信面试完了以后双方都会有意犹未尽的感受,惺惺相惜就是这么来的。

可是这种场景也不是这么容易碰到的,首先你和面试官得有相同方向的喜爱,好比你对 JVM 有很深刻的研究,而面试官对存储方面有很深刻的研究,JVM 懂的不深,这样就碰不出火花了。

因此说会有不少人碰到这么个状况:我面这个公司一面挂,另外一家公司面面超神,这都是很正常的。

固然你要是说你全能,那当我没说。

小结一下面试技巧

首先要正确的看待面试官,你和面试官是同等的,不要一来就低三下四的。

其次回答问题须要抓住重点,不要一古脑儿的把你知道的都说了,要留白待面试官提问。

要把控面试的节奏,往本身熟知的方向上引。

如何写个消息中间件

接下来我们再看看如何写个消息中间件。

首先咱们须要明确地提出消息中间件的几个重要角色,分别是生产者、消费者、Broker、注册中心。

简述下消息中间件数据流转过程,无非就是生产者生成消息,发送至 Broker,Broker 能够暂缓消息,而后消费者再从 Broker 获取消息,用于消费。

而注册中心用于服务的发现包括:Broker 的发现、生产者的发现、消费者的发现,固然还包括下线,能够说服务的高可用离不开注册中心。

而后开始简述实现要点,能够同通讯讲起:各模块的通讯能够基于 Netty 而后自定义协议来实现,注册中心能够利用 zookeeper、consul、eureka、nacos 等等,也能够像 RocketMQ 本身实现简单的 namesrv (这一句话就都是关键词)。

为了考虑扩容和总体的性能,采用分布式的思想,像 Kafka 同样采起分区理念,一个 Topic 分为多个 partition,而且为保证数据可靠性,采起多副本存储,即 Leader 和 follower,根据性能和数据可靠的权衡提供异步和同步的刷盘存储。

而且利用选举算法保证 Leader 挂了以后 follower 能够顶上,保证消息队列的高可用。

也一样为了提升消息队列的可靠性利用本地文件系统来存储消息,而且采用顺序写的方式来提升性能。

可根据消息队列的特性利用内存映射、零拷贝进一步的提高性能,还可利用像 Kafka 这种批处理思想提升总体的吞吐。

至此就差很少了,该说的要点说的都差很少了,面试官内心已经想,这人好像有点东西。

以后能够深挖的点就不少了,好比提到的 Netty,各类注册中心就能问不少,好比各注册中心之间的选型对比等。

你还提到了选举算法,因此可能会问 Bully 算法、Raft 算法、ZAB 算法等等。

你还提到了分区,可能会问这个分区和 RocketMQ 的队列有什么不一样啊?具体分区要怎么实现?

而后你提到顺序写,可能会问为何要顺序写啊?你说的内存映射和零拷贝又是什么啊?那你知道 RocketMQ 和 Kafka 用了哪一个吗?(这些我都分析过,能够看 RocketMQ 和 Kafka 底层存储之那些你不知道的事

固然还有可能问各类细节,好比消息的写入如何存储、消息的索引如何生成等等,来深挖看你有没有看过消息中间件的源码。

能够问的还不少,这篇文章我也不可能每一个点都延伸开说,这些知识点仍是得靠你们日积月累和平日的多加思考

固然往后的文章能够写一写今天提到的一些点,好比 Netty、选举算法啊,多种注册中心对比啊啥的。

面试官想问的是什么

再回到这个面试题,其实面试官想问的就是大方向上的设计,包括总体的架构、数据的流转和一些特性的把握,因此对于这个问题他想听到的就是那些重点,而不是那些细节。

而继续的深挖取决于你回答这个问题时提出的各个关键词,对于面试官自身而言熟悉的词一抓到,他就已经知道下一步要问你什么了。

因此在回答面试官的时候不只要 get 到他的点,还得为以后的回答铺路,不会说的点不要提,擅长的点多提提。

最后

以前我已经提到了,这篇文章的重点其实不在于如何回答写一个消息中间件,而在于面试的技巧。

由于面试题千千万,而技巧掌握了那么千千万的面试题都适用。

我还想提一下关于面试的一些我的见解,我我的是面试驱动学习型选手,我学习的动力就是面试,我享受面试官问我啥我都嘴角一翘微微一笑的那种不羁。

可是我不提倡那种纯粹背面试题的作法,学习是一个日积月累的过程,就像我每篇文末说的,从一点点到亿点点,又像我每篇开头都会提的,每一个时代,都不会亏待会学习的人。

个人面试驱动不只仅是说为了面试而学习,还要以面试场景来学习,什么意思呢?

学任何一种东西,都模拟一个面试官在你前面,让他从各类角度向你提问,驱动你全方位的理解一个知识点,这才是我说的面试驱动学习型选手。

因此若是你看过我以前的文章会发现我常常会提出为何呢,而后再做答。

还有一点要注意,动手能力,这很关键。

Talk is cheap, show me the code。

对了,最近搞了个群,到时候能够搞个各大厂内推啊啥的,若是想进群就备注下进群,我拉你。


我是 yes,从一点点到亿点点,咱们下篇见

本文分享自微信公众号 - yes的练级攻略(yes_java)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索