头条终面:写个消息中间件
這種設(shè)計類問題想必大家都不陌生,面試時或多或少都能碰到。
比如如何寫一個線程池?如何寫一個 HashMap ?如何寫一個 RPC 框架等等,當(dāng)然這里的寫不是真的叫你用代碼寫出來,只是說說設(shè)計理念,整體架構(gòu)。
這個面試題來自于一個讀者的字節(jié)面試經(jīng)歷,我會從面試技巧和消息中間件的設(shè)計兩個方面闡述。
我覺得重點(diǎn)在于面試技巧,因為它通用。
?
兩種極端的情況
大多數(shù)同學(xué)遇到這種問題會出現(xiàn)兩種極端的情況:
第一種:一臉懵逼,兩眼無神,不知從何說起,萬般思緒,都化作一聲嘆息。
第二種:夸夸其談,像是口中架起了一把加特林,噠噠噠噠噠噠噠噠,還冒著藍(lán)火。
第一種不用說了,好一點(diǎn)的面試官可能會引導(dǎo)你,會問一些提示性的問題,一步一步地帶你漸入佳境,當(dāng)然你要是胸中無點(diǎn)滴,那還是沒救的,場面就異常地尷尬。
第二種會把面試官整蒙了,或許你真的懂很多,很多細(xì)節(jié)也都清晰,但是你不能一股腦兒的都拋出來,這會顯得你抓不住重點(diǎn)。
?
面試官也是人
這點(diǎn)其實很關(guān)鍵,很多把面試官當(dāng)成一個莫得感情的提問機(jī)器人,覺得他無所不能可以完全 get 到你的點(diǎn),殊不知你引以為傲的細(xì)節(jié)回答,他可能覺得你在說蛇皮。
是人就會有感情,就需要交流,好的面試官會把控整體進(jìn)度,從拉家常開始,讓場子熱起來再一步一步的深挖。
當(dāng)然也有一些面試官比較弱,這時候就需要你來特意地流出一點(diǎn)空白,來讓面試官涂鴉,讓面試官感覺你這人就很舒服,你這波就穩(wěn)了。
當(dāng)然即使面對著把控全場的面試官你也得主動出擊,每個人都有自己的擅長點(diǎn),你需要引導(dǎo)面試官來詢問你的長處。
?
正確的回答姿勢
正確的回答姿勢是 BFS(廣度優(yōu)先搜索) 而不是 DFS (深度優(yōu)先搜索),什么意思呢?
就是我們需要先從大局上講出需要設(shè)計的東西的重點(diǎn),然后再等待面試官的繼續(xù)提問,深挖。
我們需要揣摩面試官的心理,從他的提問可以看出他想要知道的重點(diǎn)是哪個方向的。
比如就拿 HashMap 來說,你簡單的把獲取、寫入、沖突處理、擴(kuò)容啥的都說了,然后等待面試官接下來的提問,有可能會往線程安全方面深入,也有可能會往擴(kuò)容方向再挖,比如引出 Redis 的 hash 擴(kuò)容等等。
所以說給面試官留提問的機(jī)會,抓住他的喜好或者說熟知的方向回答,這樣如果你答得好,相互之間談的來,面試官會對你高度認(rèn)可。
而且在說各設(shè)計要點(diǎn)的時候也要注意停頓,要留機(jī)會給面試官插話,讓面試官充分參與你的設(shè)計。
還是拿 HashMap 作為例子,比如你說了獲取、寫入、沖突之后稍作停頓,這時候大概率面試官還會問還有嗎?讓面試官有參與感,讓他感覺經(jīng)過他的引導(dǎo)這個設(shè)計才逐步地完善。
當(dāng)然如果不問也沒事,你停頓下繼續(xù)說就行。
讓面試成為一場技術(shù)交流,這是面試的最高境界,相信面試完了之后雙方都會有意猶未盡的感覺,惺惺相惜就是這么來的。
但是這種場景也不是這么容易碰到的,首先你和面試官得有相同方向的喜好,比如你對 JVM 有很深入的研究,而面試官對存儲方面有很深入的研究,JVM 懂的不深,這樣就碰不出火花了。
所以說會有很多人碰到這么個情況:我面這個公司一面掛,另一家公司面面超神,這都是很正常的。
當(dāng)然你要是說你全能,那當(dāng)我沒說。
?
小結(jié)一下面試技巧
首先要正確的看待面試官,你和面試官是同等的,不要一來就低聲下氣的。
其次回答問題需要抓住重點(diǎn),不要一股腦兒的把你知道的都說了,要留白待面試官提問。
要把控面試的節(jié)奏,往自己熟知的方向上引。
?
如何寫個消息中間件
接下來咱們再看看如何寫個消息中間件。
首先我們需要明確地提出消息中間件的幾個重要角色,分別是生產(chǎn)者、消費(fèi)者、Broker、注冊中心。
簡述下消息中間件數(shù)據(jù)流轉(zhuǎn)過程,無非就是生產(chǎn)者生成消息,發(fā)送至 Broker,Broker 可以暫緩消息,然后消費(fèi)者再從 Broker 獲取消息,用于消費(fèi)。
而注冊中心用于服務(wù)的發(fā)現(xiàn)包括:Broker 的發(fā)現(xiàn)、生產(chǎn)者的發(fā)現(xiàn)、消費(fèi)者的發(fā)現(xiàn),當(dāng)然還包括下線,可以說服務(wù)的高可用離不開注冊中心。
然后開始簡述實現(xiàn)要點(diǎn),可以同通信講起:各模塊的通信可以基于 Netty 然后自定義協(xié)議來實現(xiàn),注冊中心可以利用 zookeeper、consul、eureka、nacos 等等,也可以像 RocketMQ 自己實現(xiàn)簡單的 namesrv (這一句話就都是關(guān)鍵詞)。
為了考慮擴(kuò)容和整體的性能,采用分布式的思想,像 Kafka 一樣采取分區(qū)理念,一個 Topic 分為多個 partition,并且為保證數(shù)據(jù)可靠性,采取多副本存儲,即 Leader 和 follower,根據(jù)性能和數(shù)據(jù)可靠的權(quán)衡提供異步和同步的刷盤存儲。
并且利用選舉算法保證 Leader 掛了之后 follower 可以頂上,保證消息隊列的高可用。
也同樣為了提高消息隊列的可靠性利用本地文件系統(tǒng)來存儲消息,并且采用順序?qū)懙姆绞絹硖岣咝阅堋?/p>
可根據(jù)消息隊列的特性利用內(nèi)存映射、零拷貝進(jìn)一步的提升性能,還可利用像 Kafka 這種批處理思想提高整體的吞吐。
至此就差不多了,該說的要點(diǎn)說的都差不多了,面試官心里已經(jīng)想,這人好像有點(diǎn)東西。
之后可以深挖的點(diǎn)就很多了,比如提到的 Netty,各種注冊中心就能問很多,比如各注冊中心之間的選型對比等。
你還提到了選舉算法,所以可能會問 Bully 算法、Raft 算法、ZAB 算法等等。
你還提到了分區(qū),可能會問這個分區(qū)和 RocketMQ 的隊列有什么不同啊?具體分區(qū)要怎么實現(xiàn)?
然后你提到順序?qū)?#xff0c;可能會問為什么要順序?qū)懓?#xff1f;你說的內(nèi)存映射和零拷貝又是什么啊?那你知道 RocketMQ 和 Kafka 用了哪個嗎?
當(dāng)然還有可能問各種細(xì)節(jié),比如消息的寫入如何存儲、消息的索引如何生成等等,來深挖看你有沒有看過消息中間件的源碼。
可以問的還很多,這篇文章我也不可能每個點(diǎn)都延伸開說,這些知識點(diǎn)還是得靠大家日積月累和平日的多加思考。
當(dāng)然日后的文章可以寫一寫今天提到的一些點(diǎn),比如 Netty、選舉算法啊,多種注冊中心對比啊啥的。
?
面試官想問的是什么
再回到這個面試題,其實面試官想問的就是大方向上的設(shè)計,包括整體的架構(gòu)、數(shù)據(jù)的流轉(zhuǎn)和一些特性的把握,所以對于這個問題他想聽到的就是那些重點(diǎn),而不是那些細(xì)節(jié)。
而繼續(xù)的深挖取決于你回答這個問題時提出的各個關(guān)鍵詞,對于面試官自身而言熟悉的詞一抓到,他就已經(jīng)知道下一步要問你什么了。
所以在回答面試官的時候不僅要 get 到他的點(diǎn),還得為之后的回答鋪路,不會說的點(diǎn)不要提,擅長的點(diǎn)多提提。
?
最后
之前我已經(jīng)提到了,這篇文章的重點(diǎn)其實不在于如何回答寫一個消息中間件,而在于面試的技巧。
因為面試題千千萬,而技巧掌握了那么千千萬的面試題都適用。
我還想提一下關(guān)于面試的一些個人看法,我個人是面試驅(qū)動學(xué)習(xí)型選手,我學(xué)習(xí)的動力就是面試,我享受面試官問我啥我都嘴角一翹微微一笑的那種不羈。
但是我不提倡那種純粹背面試題的做法,學(xué)習(xí)是一個日積月累的過程,就像我每篇文末說的,從一點(diǎn)點(diǎn)到億點(diǎn)點(diǎn),又像我每篇開頭都會提的,每個時代,都不會虧待會學(xué)習(xí)的人。
我的面試驅(qū)動不僅僅是說為了面試而學(xué)習(xí),還要以面試場景來學(xué)習(xí),什么意思呢?
學(xué)任何一種東西,都模擬一個面試官在你前面,讓他從各種角度向你提問,驅(qū)動你全方位的理解一個知識點(diǎn),這才是我說的面試驅(qū)動學(xué)習(xí)型選手。
所以如果你看過我之前的文章會發(fā)現(xiàn)我經(jīng)常會提出為什么呢,然后再作答。
還有一點(diǎn)要注意,動手能力,這很關(guān)鍵。
Talk is cheap, show me the code。
有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)
歡迎大家關(guān)注Java之道公眾號
好文章,我在看??
總結(jié)
以上是生活随笔為你收集整理的头条终面:写个消息中间件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面试官:Netty的线程模型可不是Rea
- 下一篇: Nhibernate一些问题解决方法