記一次慘烈的阿里秋招面試經歷

今天剛經歷了一波阿里某部門的Java技術面,內心是崩潰的。本以爲校招的難度可以低一點,結果面試官把我問到懷疑人生…

自我介紹

經歷過面試的同學們都知道,一面的第一個主題永遠是自我介紹,按照套路來唄。

我叫XXXX我來自XXXXXX大學,我今天要面試的是貴公司的
Java開發工程師,我平時主要掌握的編程語言是Java,能夠
熟練使用Java進行開發,可以熟練使用Spring、SpringMVC、
MyBatis等各種常用開發框架。

面試官:沉默五秒鐘…

技術面開始

面試官:好的,我們簡單聊聊,我看你的簡歷上有兩個項目,挑一個能體現你水平的跟我說一說吧。

我:好的,那我就跟你說一下我的XX項目吧,它用的主要的技術棧是巴拉巴拉巴拉巴拉…省略300字

面試官:好的,你在項目中遇到的最大的困難是什麼,你是怎麼解決的。

我:巴拉巴拉巴拉巴拉…結結巴巴地答完。

面試官:嗯…我看你在項目中用的數據庫是MySQL,你能跟我說說MySQL的原理嗎?

我:????????

上來就問原理,我是一臉懵逼的

我:不太知道…

這篇文章應該說的很完整了,太長了就不貼了:深入理解MySQL底層實現

面試官:嗯…沒事,可能我這麼問太寬泛了,那我問你個具體的吧,MySQL數據庫中的索引是怎麼實現的

我:MySQL的索引是基於B+樹實現的,我舉個例子吧,假設沒有索引,我們在數據庫中取數,就需要逐行遍歷整張表,假設我有幾萬、幾十萬條數據,那麼效率就會非常低,B+樹索引就可以提高效率,假設我需要找15這個數,根節點的第一個指針指向1-10,第二個指針指向10-20,第三個指針指向20-30,
那我就可以通過這個索引,找到15是在第二個指針的區間,然後到達下一個節點,下一個節點的指針又是P1:11-13 P2:14-17 P3:18-20,那我就可以找到15在P2區間,這樣在超大數據量環境下可以提高存取效率。
(回來寫博客整理了一下語言,面試時比較緊張,答的並沒有這麼清楚)

面試官:好的,那你瞭解過什麼是聚簇索引和非聚簇索引嗎?

我:不太瞭解。(漸漸崩潰,這題沒答出來挺不應該,回來一查才知道,我知道這個概念但是不知道這個名字,血虧)

聚簇索引:將數據存儲與索引放到了一塊,找到索引也就找到了數據
非聚簇索引:將數據存儲於索引分開結構,索引結構的葉子節點指向了數據的對應行,myisam通過key_buffer把索引先緩存到內存中,當需要訪問數據時(通過索引訪問數據),在內存中直接搜索索引,然後通過索引找到磁盤相應數據,這也就是爲什麼索引不在key buffer命中時,速度慢的原因
出處:聚簇索引和非聚簇索引

面試官:我看你的項目中用到了redis,你能給我說說redis的原理嗎?

我:(mmp又是原理…) redis是NoSQL數據庫,我們平時用的MySQL、Oracle都統稱爲關係型數據庫,這種數據庫的單秒存取次數遠不如redis,我知道redis是靠鍵值對存儲的,直接在內存中存儲,所以它的讀取速度和寫入速度可以非常快…

我是真不知道redis的實現原理啊…把自己瞭解的都先說了吧。

答案:Redis核心原理 - 簡書

面試官:你瞭解過redis的兩種存儲方式嗎

我:RDB和AOF,RDB就是將數據寫入一個臨時文件,持久化結束後,用這個臨時文件替換上次的持久化文件,達到數據恢復。AOF就是將執行過的指令記錄下來,數據恢復時按照順序執行一遍,實現數據恢復。

AOF(append-only file)
快照功能並不是非常耐久(durable): 如果 Redis 因爲某些原因而造成故障停機, 那麼服務器將丟失最近寫入、且仍未保存到快照中的那些數據。從 1.1 版本開始, Redis 增加了一種完全耐久的持久化方式: AOF 持久化,將修改的每一條指令記錄進文件
你可以通過修改配置文件來打開 AOF 功能:
appendonly yes
開啓後,每當 Redis 執行一個改變數據集的命令時(比如SET), 這個命令就會被追加到 AOF 文件的末尾。
這樣的話, 當 Redis 重新啓時, 程序就可以通過重新執行 AOF 文件中的命令來達到重建數據集的目的。
你可以配置 Redis 多久纔將數據fsync到磁盤一次。
出處:redis核心原理

RDB快照(snapshot)
在默認情況下, Redis 將內存數據庫快照保存在名字爲dump.rdb的二進制文件中。
你可以對 Redis 進行設置, 讓它在N秒內數據集至少有M個改動這一條件被滿足時, 自動保存一次數據集。
比如說, 以下設置會讓 Redis 在滿足60秒內有至少有1000個鍵被改動”這一條件時, 自動保存一次數據集:
出處:redis核心原理

面試官:問你個基礎的吧,數據結構學過吧,跟我說說堆排序的執行過程吧。

我:巴拉巴拉巴拉巴拉巴拉巴拉,這樣就完成了堆排序。
這題沒啥說的,就挺基礎的題,面試官可能已經不想問了吧。

面試官:你能跟我說說Java併發包中的ConcurrentHashMap的實現原理嗎?

我:(終於問到Java的題了…) ConcurrentHashMap是Java併發包中對解決HashMap線程不安全和HashTable效率低而設計的。我先跟你說說HashMap和HashTable吧,HashMap是線程不安全的,而HashTable是線程安全的,但是HashTable的線程安全是基於在HashMap上加了synchronize關鍵字實現的,所以這樣嚴重影響了存取的效率,只有一個線程能夠訪問到表,而其它線程就必須等待,這就變成了串行化的一個過程,效率極低,而HashMap效率高可又不能保證線程安全,所以ConcurrentHashMap就應運而生了,它底層採用分段鎖,是由Segment和HashEntry實現的,Segment中含有HashEntry,當多個線程訪問不同的Segment時,並不會產生衝突,只有當多個線程同時訪問一個Segment時纔會有爭奪鎖的現象發生,所以這種分段鎖的設計是非常節約資源並且提高了效率。

(我覺得這題我答的還不錯,當然這是本次面試的唯一一道Java題,我已經漸漸忘了我是面Java開發的了)

面試官:好的,那你知道Java1.7和Java1.8中ConcurrentHashMap有什麼區別嗎?

我:(…這個我還真沒好好地瞭解過,先說HashMap吧,會一點是一點) 我先說HashMap吧,HashMap在Java1.7中採用數組+鏈表的方式存儲鍵值對,當產生哈希衝突時,就將該鍵值對保存在鏈表的頭部,這樣就會有一種極端情況,假設一直產生哈希衝突,那麼這個鏈表將越來越長,我們查詢某個數也就無法達到O(1)的效果,由於這個原因,Java1.8中將HashMap做了修改,當單個桶元素超過8時,將鏈表轉換爲紅黑樹,這樣就不會再出現需要遍歷鏈表的情況,提高了讀取效率。

(顯然沒有糊弄過去,他後來還是問了ConcurrentHashMap)

1.8中的原理和實現
數據結構
JDK1.8的實現已經摒棄了Segment的概念,而是直接用Node數組+鏈表+紅黑樹的數據結構來實現,併發控制使用Synchronized和CAS來操作,整個看起來就像是優化過且線程安全的HashMap,雖然在JDK1.8中還能看到Segment的數據結構,但是已經簡化了屬性,只是爲了兼容舊版本
1.8中ConcurrentHashMap
出處:ConcurrentHashMap1.7和1.8的底層不同實現

面試官:好的,今天咱就到這吧,我的問題問完了,你保持手機暢通,後續如果有機會會再聯繫你的。

我:好的,辛苦您了。

結語

一面聊了半個小時左右,說實話聽到第一個問題的時候就覺得要涼了,複習了很久的Java各種技術,結果都沒有考到,Spring一句也沒問,感覺挺失落的。但是還是要接着學習接着準備啊,今後的側重點不應該全放在Java語言本身了,數據庫、緩存、數據結構算法都很重要,一次面試就得長一次經驗。心態還是要放平。

歡迎大家訪問我的個人博客:Object’s Blog

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章