今天給大家分享一下我的秋招提前批面試經(jīng)歷,目前三面技術(shù)面已過(guò),hr 面也面過(guò)了,正在等消息。由于內(nèi)容太多,先分享一面的面經(jīng)。
自我介紹一下吧
面試官您好,我是 xxx 大學(xué)軟件工程的一名大三學(xué)生,從大一開(kāi)始學(xué)習(xí)前端,產(chǎn)生了對(duì)編程的興趣,大二開(kāi)始接觸 Java,大二下學(xué)期學(xué)了
ssm,springboot 等框架,也做了一些項(xiàng)目。后來(lái)發(fā)現(xiàn)基礎(chǔ)很重要,于是從大三開(kāi)始一直到現(xiàn)在,一直在對(duì)基礎(chǔ)進(jìn)行學(xué)習(xí)。比如:JVM,并發(fā),操作系統(tǒng),網(wǎng)絡(luò)等。
看你的項(xiàng)目是分布式系統(tǒng),那你的上游系統(tǒng)調(diào)用你的系統(tǒng)時(shí)可能會(huì)出現(xiàn)超時(shí)的問(wèn)題,怎么處理
在我們的系統(tǒng)的話,一般有監(jiān)控平臺(tái),請(qǐng)求超時(shí)會(huì)拋出異常,會(huì)觸發(fā)企業(yè)微信郵件告警,開(kāi)發(fā)人員知道以后去看一下對(duì)應(yīng)的日志中的異常信息。查到具體是調(diào)用哪個(gè)接口出現(xiàn)的問(wèn)題,這個(gè)接口里是否調(diào)用外部系統(tǒng),定位問(wèn)題是外部的還是內(nèi)部的問(wèn)題。
那如果你看到的日志就是很多請(qǐng)求,你認(rèn)為這種是什么問(wèn)題,在外部系統(tǒng)沒(méi)有問(wèn)題的情況下核心線程池被打滿(mǎn)了
我覺(jué)得可能是有人新改了一個(gè)功能并上線,不小心寫(xiě)了死循環(huán)導(dǎo)致的 CPU 飄高。
PS:review code 的重要性
您說(shuō)的線程池爆滿(mǎn)的原因是可能一個(gè)接口中存在耗時(shí)的操作,導(dǎo)致請(qǐng)求這個(gè)接口的請(qǐng)求一直占用線程池,線程池被打滿(mǎn),從而導(dǎo)致后續(xù)來(lái)的其他接口的請(qǐng)求也會(huì)被影響。
這種情況一般可以服務(wù)降級(jí)、限流來(lái)處理。
在外部流量沒(méi)有暴增的情況下,如果你的服務(wù)每隔半個(gè)小時(shí)會(huì)出現(xiàn)服務(wù)不可用的情況,這種怎么排查
它這個(gè)是突然每隔半個(gè)小時(shí)還是其他情況?
就是這一天 11 點(diǎn)出現(xiàn)了,以后每隔半小時(shí)就會(huì)有兩分不可用,qps 都保持正常值
我猜這種情況一般出現(xiàn)在,定時(shí)任務(wù)同步一些數(shù)據(jù)到其他系統(tǒng),由于網(wǎng)絡(luò)的問(wèn)題,那邊服務(wù)慢的話就會(huì)導(dǎo)致一個(gè)超時(shí),然后就會(huì)發(fā)生這個(gè)問(wèn)題。
正常接受請(qǐng)求,也沒(méi)有任務(wù)跑,你會(huì)往哪個(gè)方面想
那它會(huì)不會(huì)受到部署機(jī)器其他服務(wù)的影響呢。
沒(méi)有
想了幾分鐘…..,這個(gè)目前還想不到其他的。
我可以給你個(gè)提示,往內(nèi)存方面想
昂,立馬 get 到點(diǎn),是可能存在內(nèi)存泄露嗎?是不是由于存在內(nèi)存泄露導(dǎo)致 full gc,gc 太頻繁導(dǎo)致的。
對(duì),那這種問(wèn)題怎么排查解決
如果內(nèi)存溢出的話,一般可能會(huì)有 OOM 拋出,JVM 可以設(shè)置參數(shù)在出現(xiàn) OOM 時(shí) dump 下內(nèi)存的鏡像,然后你可以利用一些分析工具,分析這個(gè) dump
文件,有的工具直接可以給你一些優(yōu)化建議,或者你可以找到哪個(gè)類(lèi)的內(nèi)存使用情況,找到內(nèi)存泄露的點(diǎn),去看代碼。一般是 NIO 引起的,因?yàn)?Java 8
開(kāi)啟方法區(qū)使用的是元空間,不是永久代了。元空間是本地內(nèi)存,不是堆內(nèi)存,不受 JVM 管理,由操作系統(tǒng)管理,所以使用不當(dāng)可能會(huì)出現(xiàn)內(nèi)存泄露的問(wèn)題。
好,那下一個(gè)問(wèn)題,你那邊用的是 dubbo 把
是
是借鑒 dubbo 開(kāi)發(fā)的一個(gè) rpc 框架吧
正常 Java 用的是 dubbo,之前是 php,為了 php 和 java 微服務(wù)之間的跨語(yǔ)言調(diào)用,實(shí)現(xiàn)了一個(gè)跨語(yǔ)言的 rpc,現(xiàn)在已經(jīng)全部轉(zhuǎn)為
Java 了,都用 dubbo 調(diào)用。而且微服務(wù)架構(gòu)方面又做了改進(jìn),使用了 Service Mesh,面向云原生。
dubbo 服務(wù)的啟動(dòng)、注冊(cè)流程,說(shuō)一下
首先,有個(gè)服務(wù)的提供者啟動(dòng)起來(lái)后,會(huì)先向服務(wù)注冊(cè)中心注冊(cè)服務(wù),如果是 zk 的話,它就是在某個(gè) dubbo 的目錄下注冊(cè)上下,其他消費(fèi)者想調(diào)用的話,就從
zk 上把對(duì)應(yīng)的提供者的 ip 地址啥的拉下來(lái)緩存起來(lái)。然后就可以調(diào)用了。
那提供服務(wù)的提供者 ip 更改了,消費(fèi)者是如何動(dòng)態(tài)感知服務(wù)提供者的改變呢
一般分布式注冊(cè)服務(wù)可以動(dòng)態(tài)感知。如果是 zk 的話,服務(wù)提供者在 zk 上注冊(cè)服務(wù)時(shí)創(chuàng)建的是臨時(shí)節(jié)點(diǎn),如果服務(wù) ip 更改了或者服務(wù)掛了,服務(wù)的調(diào)用者通過(guò)
zk 的 watch 機(jī)制可以監(jiān)聽(tīng)到服務(wù)提供者目錄下的節(jié)點(diǎn)增加、刪除、修改事件。
你用到了很多隊(duì)列,kafka、rabbitmq 了解嗎
我現(xiàn)在這邊用的是 nsq 和 kafka,kafka 一般是大數(shù)據(jù)那邊離線處理一些東西,nsq
一般是告警信息,兩個(gè)系統(tǒng)之間進(jìn)行解耦,進(jìn)行信息交互時(shí),發(fā)消息到 nsq。區(qū)別的話,kafka 對(duì)大數(shù)據(jù)處理能力比較好,nsq
的話一般作為一個(gè)正常的消息隊(duì)列,同步改異步就可以用 nsq。
既然 Kafka 可以處理大數(shù)據(jù),那為什么不用 kafka,而用 nsq 呢?
這個(gè)問(wèn)題我之前想過(guò),問(wèn)過(guò)我的 leader。kafka 一般是大數(shù)據(jù)那邊流處理什么的,它那邊一般都只接受 kafka 的消息,和大數(shù)據(jù)集成比較好。至于選
nsq 的話,它是結(jié)合當(dāng)時(shí)的業(yè)務(wù)場(chǎng)景選擇的,這個(gè)也沒(méi)有選哪個(gè)好哪個(gè)壞。
那他當(dāng)時(shí)選型的時(shí)候,為什么不用 kafka
因?yàn)?kafka
貌似對(duì)于延時(shí)消息等支持的不太好,事務(wù)這些,它雖然對(duì)大數(shù)據(jù)的處理的好,但是它也有缺漏的地方,它有它的專(zhuān)攻方向,比如:吞吐量方面,但是也有它的不足之處,就好比計(jì)算機(jī)中的摩爾定律。一般業(yè)務(wù)系統(tǒng)常需要一些延時(shí)消息就需要用
nsq 了。
根據(jù)我的項(xiàng)目問(wèn)的一些問(wèn)題
……
有數(shù)據(jù)庫(kù)調(diào)優(yōu)經(jīng)驗(yàn)嗎?對(duì)于數(shù)據(jù)庫(kù)有多索引匹配時(shí),有什么經(jīng)驗(yàn)嗎
這個(gè)匹配的話,比如:ABC 三個(gè)組合索引,必須要順序執(zhí)行,比如 A = 2,C =2 。這個(gè)時(shí)候就不會(huì)執(zhí)行,因?yàn)樗茐牧隧樞蛐浴?
你說(shuō)這種情況是完全用不到嗎
是的,因?yàn)樗粷M(mǎn)足索引的最左匹配原則。
那比如說(shuō),我數(shù)據(jù)庫(kù)有多個(gè)索引,A,B,BC,一個(gè)查詢(xún)條件 A,B,C 都有,那一般怎么查看呢
這個(gè)一般的話是用 explain 去分析一下 sql 的執(zhí)行計(jì)劃,它會(huì)輸出可能走的索引,真正走的索引,掃描的行數(shù),額外的消耗(extra),用沒(méi)用臨時(shí)表等。
那它分析出來(lái)的索引就是數(shù)據(jù)庫(kù)一定會(huì)用的索引嗎
explain 分析出來(lái)的嗎
或者說(shuō),你覺(jué)得它 explain 分析出來(lái)的就是最佳的索引嗎
一般情況下最佳的,數(shù)據(jù)庫(kù)會(huì)根據(jù)你的
sql,通過(guò)解析器生成對(duì)應(yīng)的語(yǔ)法分析樹(shù),它對(duì)這個(gè)樹(shù)進(jìn)行一些規(guī)則的優(yōu)化后,會(huì)生成一些查詢(xún)計(jì)劃,通過(guò)基于時(shí)間成本的分析算法選出一個(gè)盡可能是最佳的查詢(xún)計(jì)劃。這個(gè)具體合不合適很難說(shuō)。
你沒(méi)有遇到建的索引不好,導(dǎo)致走的索引是最差的情況嗎
這個(gè)一般的話,可能是你對(duì)索引一無(wú)所知,導(dǎo)致一些索引的規(guī)則不去遵守,而且數(shù)據(jù)庫(kù)索引的匹配規(guī)則很多,很容易走坑。如果你的業(yè)務(wù)一定要走你設(shè)置的那個(gè)索引,mysql
也可以通過(guò)設(shè)置強(qiáng)制走你設(shè)置的某個(gè)索引。
你對(duì) Java8 了解嗎
了解,因?yàn)槲椰F(xiàn)在參與的項(xiàng)目就大量用了 Java8 的特性。比如:stream,lambda 表達(dá)式,時(shí)間 API 等。具體應(yīng)用場(chǎng)景的話,比如你一個(gè)接口要返回
VO List 集合,而你數(shù)據(jù)庫(kù)查出來(lái)的是 DO List 集合,這個(gè)時(shí)候你就可以用集合的 stream
去做這個(gè)轉(zhuǎn)換。相比于傳統(tǒng)的寫(xiě)法,代碼會(huì)變的很簡(jiǎn)單和清爽。
流式編寫(xiě)代碼的好處和壞處可以說(shuō)一下嘛
好處的話,寫(xiě)代碼的效率快了,看和很舒服。
壞處的話,流式性能不怎么好,并發(fā)情況很多的情況下才體現(xiàn)出好。
我覺(jué)得最主要的是,之前你自己寫(xiě)的話,就面向過(guò)程化了。流式的話,Java8
提倡的是面向函數(shù)式編程嘛。編程模型之前最開(kāi)始是面向過(guò)程,然后面向?qū)ο螅嫦蛟幊?,面向切面編程,面向函?shù)式編程,以后 java9
的面向模塊化編程。而且把過(guò)程封裝在函數(shù)中,通過(guò)函數(shù)去轉(zhuǎn)換數(shù)據(jù)的狀態(tài)對(duì)于線程安全方面也有很大的好處。
如果數(shù)據(jù)庫(kù)對(duì)一些記錄存在熱點(diǎn)更新操作,有大量的更新,怎么解決呢
一般可以利用多級(jí)緩存去解決。如果數(shù)據(jù)量太猛增的話,你用 redis 客戶(hù)端訪問(wèn) redis 服務(wù)端都訪問(wèn)不到,因?yàn)閹挶淮驖M(mǎn)了嘛。這種情況可以提前去探測(cè)某個(gè)
key 是不是熱點(diǎn),然后在本地緩存操作。
你怎么即時(shí)同步數(shù)據(jù)給其他人呢
它會(huì)有一個(gè)算法提前探測(cè)某個(gè) key 是否是熱點(diǎn),然后框架會(huì)幫你進(jìn)行本地緩存的管理。
數(shù)據(jù)庫(kù)有單熱點(diǎn),那你怎么解決
這種一般先做一個(gè)緩存,然后可以用消息隊(duì)列削峰填谷。
操作緩存可能會(huì)超時(shí),你怎么保證這個(gè)數(shù)據(jù)的正確性呢?因?yàn)槟慵恿司彺嫜?br>
對(duì)對(duì),這個(gè)數(shù)據(jù)庫(kù)和緩存保持一致性比較難保證。而且大量數(shù)據(jù)訪問(wèn)更新,也不能加鎖,因?yàn)閿?shù)據(jù)庫(kù)通過(guò)行鎖保證線程并發(fā)安全問(wèn)題。
我要你解決的就是行鎖等待導(dǎo)致的性能被拉低的問(wèn)題,用緩存也是可以的,但是不能保證 100% 的數(shù)據(jù)一致性,那我的業(yè)務(wù)場(chǎng)景就是想要 100%
的數(shù)據(jù)一致性,你現(xiàn)在有大概的解決思路嗎
這個(gè)可以用多套數(shù)據(jù)庫(kù)主從集群來(lái)解決嗎?通過(guò)這種方式來(lái)提升數(shù)據(jù)庫(kù)的寫(xiě)性能。讓多個(gè)集群去抗。數(shù)據(jù)庫(kù)中間件可以把流量分散到各個(gè)主從集群中的主庫(kù)上。
可以,這算是一種解決方案,那還有其他辦法嗎
你打破這個(gè)行鎖就行了
…… 我再想想。這個(gè) ……
主要是單條記錄引起的,它就是頻繁更新引起的。
昂,這個(gè)是不是可以……… 我看 JDK 源碼,頻繁更新它一般是: HashMap 是非線程安全的,后來(lái)出現(xiàn)了線程安全版的
HashTable,但是它性能比較差,因?yàn)樗苯泳蛯?duì)整個(gè) hash 表進(jìn)行了加鎖。后來(lái)出現(xiàn)了
CurrentHashMap,出現(xiàn)了分段鎖,降低了鎖的粒度,其實(shí)就是一種思想,你對(duì)一個(gè)熱點(diǎn)數(shù)據(jù)的訪問(wèn)的話,就是分而治之,多去搞幾個(gè),均攤一下。難道是利用
hash 一致性算法把這些寫(xiě)請(qǐng)求,多分幾張表。
差不多吧,思想就是分而治之,只要把單點(diǎn)數(shù)據(jù)拆分掉,讓它變成多條數(shù)據(jù),然后去更新多條數(shù)據(jù),最后再合成一條。
嗯嗯?,F(xiàn)在大數(shù)據(jù)一般也這樣,大的搞不動(dòng)就拆分。
從和你的對(duì)話來(lái)看,我覺(jué)得你基礎(chǔ)也不錯(cuò),基礎(chǔ)我就不問(wèn)了,我這邊沒(méi)有什么問(wèn)題了,我看你這邊,實(shí)習(xí)經(jīng)歷豐富,offer 收的也挺多。你有什么想問(wèn)的
貴公司的技術(shù)棧,還有如果我進(jìn)去以后所在的產(chǎn)品線。
面試官講述了他們公司的技術(shù)棧和一些業(yè)務(wù)
面試官對(duì)我的一些職業(yè)規(guī)劃的建議
多鍛煉自己的技術(shù)思維 + 業(yè)務(wù)思維,可以往業(yè)務(wù)中臺(tái)方向走。更好的支持別人的業(yè)務(wù),技術(shù)主要服務(wù)于技術(shù),要培養(yǎng)業(yè)務(wù)架構(gòu)思維。
總結(jié)
我覺(jué)得面試過(guò)程中要避免自己一直在說(shuō),可以多和面試官去互動(dòng),去問(wèn)面試官是不是這樣子,這樣可以避免你理解錯(cuò)面試官的問(wèn)題。我們的項(xiàng)目可能大部分是
CRUD,但是我們的思維不可以停留在 CRUD,多去結(jié)合業(yè)務(wù),也就是結(jié)合場(chǎng)景去思考你項(xiàng)目,這可能是一個(gè)很大的優(yōu)勢(shì)。畢竟技術(shù)是用于服務(wù)業(yè)務(wù),去解決業(yè)務(wù)需求。
**整理面經(jīng)不易,花了我周末大部分的時(shí)間,如果覺(jué)得寫(xiě)的好話,歡迎關(guān)注公眾號(hào)、轉(zhuǎn)發(fā),你們的支持是我繼續(xù)寫(xiě)后續(xù)面經(jīng)的動(dòng)力。**
搜索微信公眾號(hào):Java知其所以然,可免費(fèi)領(lǐng)取某課、Java 后端面經(jīng)等資源,還有統(tǒng)一環(huán)境(教你怎么配置一套開(kāi)發(fā)環(huán)境)視頻領(lǐng)取。
熱門(mén)工具 換一換
