本文轉載自:微信公眾號【Java極客技術】 作者: 子悠
博客地址:http://www.justdojava.com/2019/03/28/cd-ali-interview/#
微信公眾號地址:https://mp.weixin.qq.com/s/7M66smtt_pTlRNtfGMS2kQ
2015在實習的時候,當時一個一起實習的朋友在2019年3月份的時候突然在微信上找我,問我要不要面試下螞蟻金服。問了下相關信息才知道他在2018年11月的時候進到螞蟻金服,現在招人就想到了我,問我要不要試一下。
剛開始還是有所顧慮的,因為畢竟是大廠,進去應該不容易,但是這個朋友進去了,想想應該也沒有很難吧,畢竟當時實習的時候,他技術并不怎么樣。但是畢竟過去好幾年了,現在人家可能變厲害了。所以一開始并沒有急著提交簡歷,而是說準備下再提交簡歷。然后就準備了一周,寫簡歷,刷題,在網上找螞蟻金服的面經。提交了一份簡歷,然后發現簡歷上面沒有寫學歷,幸好他還沒提交,就修改了下重新發了一份,然后他又給我提了幾個建議,所以又改了一版,才最終提交。
提交簡歷后的第二天下午,上班的時候螞蟻金服的面試官打電話過來了,說要面試,當時正在上班,就說了下不方便,就約了當天晚上再面試。誰知道當天小組因為來了新人,晚上要聚餐,所以沒辦法,就厚著臉皮給面試官發了短信,說了下晚上臨時有事不能參加,想約下第二天或者周末。沒想到面試官很理解,主要提出第二天晚上八點面試,短信上還讓我好好準備,好好加油。
題外話:
有時間沖突的時候及時跟面試官溝通,往往第一面是技術面,大家都是做技術的,能理解的。
平時多交點朋友往往會有意外的驚喜
電面一
第二天晚上六點多快七點的時候面試官提前打電話了,這天是周五幸好及時下班,原本是想著早點下班回去再準備準備,誰知道電話來的那么突然,剛點好晚飯,還沒來得及吃。既然電話都打來了,那就面唄,就到店外面面試了。
流程
1、2分鐘的自我介紹
大致講了自己的姓名,畢業院校,哪年畢業,個人愛好以及平時空閑時間做點什么,這個如實回答就好。因為之前有面試過,所以準備過。建議可以自己提前寫下來,多說幾遍,找點感覺。
2、你自己認為自己最熟悉的技術是什么?
這個就因人而異了,每個人熟悉的東西都不一樣,一定要說自己最擅長的東西,不要給自己挖坑。因為面試官下一步就會根據你的回答進行提問。對于我來是,工作了幾年學的東西多而雜,沒有什么很深入的,但是總不能說沒有吧,所以就說了 Java 開發比較多,所以 Java 語言熟悉多一點。然后面試官就說:“好,那我就問你一點 Java 語言方面的。”
3、 HashMap 底層實現原理是什么?
這個作為一個面試必問的題目,所以我還是提前準備過的,看過源碼。所以這個問題不是問題,答完,面試官說回答的對了。
HashMap,HashTable,ConcurrentHashMap 面試必備,針對1.7和1.8的不同實現加以說明。包括底層的數據結構,Hash 碰撞生成鏈表,Java8的鏈表轉紅黑樹。
4、Java 的多線程有沒有使用過
根據自身情況,用過就用過,沒用過就沒有用過。我回答有簡單的使用過,但是使用的場景不多。面試官也就沒追問了,說了沒關系,就繼續。
5、講一下線程池,以及實現固定大小線程池底層是如何實現的?
講了下四中線程池,單一線程池,固定大小線程池,緩存線程池,定時線程池。但是關于固定大小線程池底層是如何實現的,回答的不好,面試官直接問底層的源碼是不是沒看過,就說是的。面試官說沒關系。。。
追加:線程池底層都是通過
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
來實現的。
corePoolSize
: 表示需要設置的線程個數;
maximumPoolSize
: 線程池允許的最大線程個數;
keepAliveTime
: 空閑線程存活的時間,超過這個時間就會被回收;
unit
: 存活時間的單位;
workQueue
: 需要執行的任務隊列。
threadFactory
: 線程工廠,用于創建線程,一般用默認的即可;
handler
: 拒絕策略,當任務太多來不及處理,如何拒絕任務;
拒絕策略:
直接丟棄(DiscardPolicy)
丟棄隊列中最老的任務(DiscardOldestPolicy)
拋異常(AbortPolicy)
將任務分給調用線程來執行(CallerRunsPolicy)
6、Redis 為什么這么高效,使用的場景是什么?
回答了一下我們使用 redis 做緩存和登錄 session 存在的場景,以及 redis 是單線程的。
1、完全基于內存,大多數請求都是內存操作,非常快速;
2、數據結構簡單,操作簡單;
3、采用單線程,避免了不必要的上下文切換和競爭條件,不存在多進程或者多線程的切換,不用考慮鎖帶來的性能消耗;
4、使用多路 I/O復用模型,非阻塞 IO
7、分布式服務是否了解,zookeeper,dubbo 是否使用過?
關于 zk 和 dubbo 這塊用的不多,zk 主要是在使用 kafka 的時候會用到,但是不涉及原理上面的研究。dubbo 雖然項目中有用過,但是并不是很深入,就沒說用過,直接說沒用過。
8、冪等概念有沒有了解過
冪等性是數學上的含義是對于參數 x,f(x)=f(f(x));比如絕對值函數。
在分布式環境下表示的是對于同樣的請求,在一次或者多次請求的情況下對系統的使用資源是一樣的。保證失敗重試不會導致提交兩次。
方法:
帶版本號的方式;
采用數據庫唯一索引方式;
9、常用的數據庫是什么?
我們常用的數據庫是 MySQL,所以就回答了 MySQL。
10、MySQL 的事務特性有哪些?
- 首先事務是作為單個邏輯工作單元執行的一系列操作,這些操作作為一個整體一起向系統提交,要么都執行,要么都不執行。事務是一個不可分割的邏輯單元。
- A(原子性)事務的各步操作是不可分的,保證一系列的操作要么都完成,要么都不完成;
- C(一致性)事務完成,數據必須處于一致的狀態;
- I(隔離性)對數據進行修改的所有并發事務彼此之間是相互隔離,這表明事務必須是獨立的,不應以任何方式依賴或影響其他事務;
- D(持久性)表示事務對數據處理結束后,對數據更改必須持久化,不管是事務成功還是回滾。事務日志都能夠保持事務的永久性。
11、如果現在一臺生產的數據庫掛了怎么處理?
首先這題沒有 get 的面試官想問的點是什么,所以就根據自己項目本身的情況做答了。我們項目生產上的數據庫是有主備的,在主數據庫掛掉的情況下是會切換到備數據庫,先保證業務的穩定性,然后在對崩潰現場進行保留,方便后續分析問題,找到原因。這里面試官追問了一下,我們主備的切換是自動的還是手動的,這個由于是公司運維團隊負責的,自己本身不是特別清楚,但是根據對公司運維團隊的了解,應該是自動的。所以就這樣如實的回答了。
12、數據庫如何實現 rollback 的?
數據庫在寫入數據之前是先講對數據的改動寫入 redo log 和 undo log,然后在操作數據,如果成功提交事務就會講操作寫入磁盤;如果失敗就會根據redo log 和 undo log 逆向還原到事務操作之前的狀態。
13、工作這么久你遇到的最難的技術點是什么?
我這邊根據具體的工具經理,回答的是 kafka 的初次使用,因為當時是公司內部第一個引入 kafka,之前沒有小組使用過,所以要采很多坑。并且那個時候 kafka 還沒有發布1.0版本,官網和網上提供的版本很雜亂不兼容。
14、用過Kafka 的話說下 Kafka優缺點有哪些?
- Kafka 是一個高吞吐量的消息隊列。基本的組件有生產者,消費者,node 節點,生產者負責生產消息,將消息發送到指定的 topic 或者 partition 當中。
- 每個 partition 可以有多個分區副本,并且存放在不同的 broker 節點上,保證數據的安全。partiton 的底層是根據 segment 段存放的一系列日志文件,文件里面存放的具體的消息內容,每條消息都有一個唯一的 offset 偏移量,并且是按照磁盤順序存放的。由于磁盤是順序讀寫,所以 kafka 可以有很高的吞吐量。磁盤的順序讀寫比隨機讀寫的性能高很多。
- 每個消費者都屬于一個消費者組,可以消費指定 topic 下的數據。
15、TCP/IP 協議是如何保證數據可靠性的?
首先 TCP是面向連接的傳輸協議。主要通過消息確認和重試機制來保證數據傳輸的可靠性。
電面二
二面的時間是在第二周,周四下午的時候打電話過來,問是否可以面試。但是當時在上班就說不方便,能否周五晚上面試。面試官說可以。誰知道,第二天中午還沒下班就打電話過來說面試,可能本來周五大家各自事情都多吧,他也想盡快搞完。我這邊被突然的面試電話給搞懵了一下,想著不是約好了晚上么,怎么搞突擊。。。但是沒辦法,已經推過一次,沒好意思再推掉。就說了我要找個安靜地方,稍等下。
整個面試過程不是很好,主要是在公司內部找了個沒人的地方,說話聲音都不敢大,而且還經常有人經過,來來回回的。感覺這點沒有決策好,也是這次的一個遺憾。所以大家電話面試的時候一定要找個沒人的地方。
流程
1、先進行自我介紹,然后介紹自己做過的項目,從項目流程架構設計等方面介紹
根據個人經歷說了自己所做的項目,以及流程和架構方面,因為是自己參與的項目,所以整個流程說的還是很流暢的。畢竟自己很熟悉。這塊盡量多從幾個方面講,流程,架構,設計等。
2、HashMap 的查詢時間復雜度
理想情況下是 O(1)的,但是實際中會出現 hash 碰撞,導致無法達到效果。
3、LinkedList和ArrayList的區別
- LinkedList 底層是基于雙向鏈表實現的,而 ArrayList 底層是基于動態數組實現的;
- 查詢的時候 LinkedList 的效率要低于 ArrayList,因為 LinkedList 需要遍歷鏈表,而 ArrayList 底層數組根據下標直接獲取數據。
- 插入刪除數據的時候,LinkedList 效率比ArrayList 效率高,因為 ArrayList 在數據多的情況下會進行數組擴容或移動數組。
4、多進程與多線程在編程上面有什么需要注意的
首先進程是資源分配的最小單元,線程是任務調度的最小單元
對比維度 | 多進程 | 多線程 | 總結 |
---|---|---|---|
數據共享、同步 | 數據共享復雜,需要用IPC;數據是分開的,同步簡單 | 因為共享進程數據,數據共享簡單,但也是因為這個原因導致同步復雜 | 各有優勢 |
內存、CPU | 占用內存多,切換復雜,CPU利用率低 | 占用內存少,切換簡單,CPU利用率高 | 線程占優 |
創建銷毀、切換 | 創建銷毀、切換復雜,速度慢 | 創建銷毀、切換簡單,速度很快 | 線程占優 |
編程、調試 | 編程簡單,調試簡單 | 編程復雜,調試復雜 | 進程占優 |
可靠性 | 進程間不會互相影響 | 一個線程掛掉將導致整個進程掛掉 | 進程占優 |
分布式 | 適應于多核、多機分布式;如果一臺機器不夠,擴展到多臺機器比較簡單 | 適應于多核分布式 | 進程占優 |
5、ThreadLocal的使用場景
ThreadLocal 適用于每個線程需要自己獨立的實例且該實例需要在多個方法中被使用,也即變量在線程間隔離而在方法或類間共享的場景。
6、堆內存和棧內存有什么區別
- 堆內存是線程共享的,棧內存是線程私有的;
- 堆內存用來存放由new創建的對象和數組,棧內存中存放一些基本類型的變量和對象的引用變量;
7、堆排序時間復雜度
排序名稱 | 穩定性 | 平均時間復雜度 | 最好時間復雜度 | 最壞時間復雜度 |
---|---|---|---|---|
桶排序 | 不穩定 | O(n) | O(n) | O(n) |
基數排序 | 穩定 | O(n) | O(n) | O(n) |
歸并排序 | 穩定 | O(nlogn) | O(nlogn) | O(nlogn) |
快速排序 | 不穩定 | O(nlogn) | O(nlogn) | O(n^2) |
堆排序 | 不穩定 | O(nlogn) | O(nlogn) | O(nlogn) |
冒泡排序 | 穩定 | O(n^2) | O(n) | O(n^2) |
選擇排序 | 不穩定 | O(n^2) | O(n^2) | O(n^2) |
8、如果優化數據庫的數據查詢,另外應用層上還能如何優化?
1)數據庫層面上:
- 除了主鍵索引,唯一索引之外,對于常用的查詢字段也要加索引。查詢的時候盡量使用主鍵索引,因為MySQL 的 InnoDB 的主鍵索引索引的是整行數據,而普通索引索引的是主鍵,會有回表操作。當然索引并不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,需要酌情考慮。
2、優化查詢語句,盡量采用確認性查詢語句,減少 or,in,not in,%xxx%語法的使用。
2)應用層面上:
- 采用緩存機制,將常用的數據進行緩存,增加訪問速度;
- 分庫分表,讀寫分離,將數據分開讀寫,提升性能
9、強一致性,弱一致性,最終一致性
- 強一致性:對于更新后的數據,要求后續所有節點的任何操作都要獲取最新值的情況;
- 弱一致性:對于更新后的數據,后續節點的數據操作可以是新值,也可以是舊值,通過一段時間后后續節點對數據的操作都是新值;
- 最終一致性:是弱一致性的特殊形式,存儲系統保證在沒有新的更新的條件下,最終所有的訪問都是最后更新的值。
10、有一個一百萬行的文件,內部是購買的商品ID,如何獲取到購買最多的前一百個商品。
- 思路:首先考察的肯定是大數據處理方案,這些數據肯定不能一次性讀取到內存,那就需要拆分,將數據分隔處理。假設要分隔為 n 個文件。
- 分隔:如果 ID 是整型的話,可以直接采用取模(id % n)的方式;如果 ID 是字符串可以先計算 hash 值然后再取模(hash(x) % n)的方式,將相同 ID 的商品分到同一個文件中。
- 針對每個小文件進行 top100的排序,返回購買最多的100個商品 ID
- 根據 n 個文件中的100個 ID,在進行一次排序,即可得到需要的數據。
小結
首先很感謝內推的那個朋友才有了這次的面試機會,雖然結果不盡人意,但是為自己的學習成長之旅增加了一些精彩。
然后說下這次的面試體驗,總得來說,感覺不是很好,因為幾次打電話都是在公司上班期間,畢竟在公司接到面試電話還是很不好的。沒有按照約定的時間點打電話,可能是我接觸的少,不知道其他公司是怎么樣的,總覺得這樣不太好。
身為一個目前在職三年,工作在深圳這樣的大環境下,還是有很大壓力的。以前上學的時候想著什么時候能月入過萬應該就不愁什么的,但是漸漸的發現,即使月入過萬也還是過不好生活。周圍比你厲害比你強的人多了去了,你能做的就只有不斷的學習,不斷的進步。