每個時代,都不會虧待會學習的人。
大家好,我是 yes。
這種設計類問題想必大家都不陌生,面試時或多或少都能碰到。
比如如何寫一個執行緒池?如何寫一個 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,從一點點到億點點,我們下篇見。