兩年經驗拿到螞蟻/頭條 Offer(面經分享)

Java技術棧
www.javastack.cn
關注閱讀更多優(yōu)質文章
反思:自己是不是真的要離職,假如不離職,在老東家接下來應該做什么才能繼續(xù)提升?
定位:我在硬性技能(編碼、架構)上的長處在哪?我在軟技能(溝通,團隊)上的長處在哪?這步順帶寫了簡歷
尋找平臺:哪些平臺能同時滿足:1、有挑戰(zhàn)有上升空間;2、符合我的定位方向;3、團隊氛圍和老東家一樣好(或更好)
找人內推:基本都是在 v2 上找的(誠摯感謝各位幫助我內推的大佬)
面試談 offer
假如我是面試官,我會招怎樣的人進來做我的同事?
對于一個畢業(yè)兩年多的人,我最希望他有什么特質?這個階段的人其實還是”空杯”,我希望他有很強的學習能力和進取心,給自己部門培養(yǎng)出一個超級生產力;
什么樣的行為會讓我”討厭一份簡歷”:把每個項目都大寫特寫,尤其是陳述細節(jié)沒有重點;羅列框架當能力,用過了一類場景的框架就覺得能解決一類業(yè)務諸如此類;
面試的時候我會偏向于問哪些問題?一是簡歷上寫了”理解”或”精通”的語言與中間件;二是簡歷上寫得比較有趣,又沒有完全交代清楚的項目;
PingCAP - Cloud 方向
螞蟻 - 容器調度方向(CTO線)
頭條 - 工程效能方向
PingCAP
面試前
一面
二面
問項目經歷,聊了兩個項目
對 Kubernetes 了解怎么樣,看過源碼嗎?
k8s 的代碼我以前其實只看過 kubelet,臨陣磨槍的時候把 apiserver、scheduler、controller-manager 都看了一遍,笑容漸漸出現。
Kubernetes 的 Service 是什么概念,怎么實現的?
你剛說到 Informer,Informer 是怎么實現的,有什么作用?
StatefulSet 用過嗎?有什么特點?
StatefulSet 的滾動升級是如何實現的?
現在我們希望只升級 StatefulSet 中的任意個節(jié)點進行測試, 可以怎么做? 這題沒有思路,只好強答用”兩個 StatefulSet”,后來一想起一個新的 StatefulSet 那 PV 里的數據就丟了,其實正確辦法是利用 partition 機制,笑容漸漸消失。
Kubernetes 的所有資源約定了版本號, 為什么要這么做?第二個拿不準的問題,我面試前就反復告訴自己”不要強答“以及”不知道的題就講思路“,于是就說這塊代碼確實沒看過,但是根據微服務 API 的設計理念,版本號的作用有巴拉巴拉。答完似乎面試官還算滿意,于是又往下挖了一句:
假如有多幾個版本號并存, 那么 K8S 服務端需要維護幾套代碼?這題完全不知道,內心逐漸焦灼,立馬走老套路”這我沒看過 k8s 代碼怎么寫的無法確定(想表達自己真正看過代碼才會確認,凸顯自己嚴謹…我的媽呀),但假如由我來寫這份代碼(裝作非常自信),我會只會維護一份最新的 Model,然后設計對應一個版本段的 Adpater 將老版本的 Model 轉化過來巴拉巴拉”。到這里我已經虛的不行了
OK,那接下來我們聊聊 Golang (我:長舒一口氣)
看一下這段代碼有沒有問題(一段 golang for-range 里 goroutine 閉包捕獲的代碼),為什么?
goroutine 是怎么調度的?
goroutine 和 kernel thread 之間是什么關系?
有什么想問我的?
三面
給我介紹 PingCAP 相關團隊的職責與挑戰(zhàn)
聊為什么出來看機會,以及未來的職業(yè)規(guī)劃
聊我之前做的一個數據同步的項目,大概內容是訂閱 MySQL Binlog,sink 到搜索索引、分庫分表以及業(yè)務事件訂閱流中
為什么數據同步里選擇了 xxxx 開源項目,優(yōu)勢在哪?
訂閱分庫分表的 Binlog 怎么訂閱?
分庫分表的數據源中假如存在主鍵沖突要怎么解決?
怎么保證下游對 Binlog 的消費順序?
如何在下游保證消費時的事務原子性?
描述了一下 tidb 的 binlog 架構,問這種場景下怎么保證 Binlog 順序
聊一個上了 Kubernetes 的項目,問了一些細節(jié)和坑
用 Kubernetes 之后,解決了哪些問題?
聊我之前做的監(jiān)控警報項目,問背景和產出
Prometheus 單實例數據量級 hold 不住了,有什么解決方案?
有什么想問我的?
四面
聊”配置中心”項目的細節(jié)
為什么不用 ZK,要自己再寫一個”配置中心”, 這個問題讓我措手不及,我只好坦白:當時年輕,想刷經驗,事后才領悟到不要重復造輪子,當然最后系統(tǒng)的產出也不錯(后面這兩句是我臨時加的,不能讓面試官覺得我是一個不看全局只顧自己刷經驗的人)
配置中心怎么做服務發(fā)現的?怎么做 failover 的?
用 Kubernetes 碰到過哪些坑?
對 Prometheus 做了哪些改動?
對 Alertmanager 做了哪些改動?
監(jiān)控系統(tǒng)怎么做”自監(jiān)控”?
跨機房的網絡問題怎么監(jiān)控?
有什么想問我們的?
五面
PingCAP 小結
面試難度:正常
面試體驗:我給滿分
問題偏向:項目經歷、工程能力
面試前
一面
介紹一下自己
問項目經歷, 聊”數據同步”
接著聊上了 K8S 的項目
有沒有什么鉆研得比較深得技術?(我:kubernetes, golang, prometheus, java)
kubernetes 的架構是怎么樣的?這個問題很大,拆成 apiserver、controller、kubelet、scheduler 講了一下
golang 與 java 的比較, 這個問題又很大,當時主要對比了 vm、協(xié)程支持、面向對象和泛型的區(qū)別、以及自己對各自使用場景的一些理解
golang 的 gc 算法, 知道是三色標記,不過細節(jié)說不上來
從無限的字符流中, 隨機選出 10 個字符, 沒見過也沒想出來,查了一下是蓄水池采樣算法,經典面試題,沒刷題吃虧了
怎么擴展 kubernetes scheduler, 讓它能 handle 大規(guī)模的節(jié)點調度
單節(jié)點提速:優(yōu)選階段隨機取部分節(jié)點進行優(yōu)選;水平擴展 scheduler 節(jié)點,pod 做一致性 hash 來決定由哪個 scheduler 調度
你有什么想問我的?
二面
先聊了聊項目
給 Prometheus 做了哪些改動?
自研配置中心, 具體做了哪些內容?
有用過 MySQL 的什么高級特性嗎?這里不太理解,我問什么算高級特性,面試官就切換到了下一個問題
配置中心的核心數據表是怎么設計的?
為什么在業(yè)務里用 Redis, Redis 有什么優(yōu)點?
單線程:并發(fā)安全;高性能;原語與數據結構豐富;采用廣泛,踩坑成本低
對 Redis 里數據結構的實現熟悉嗎?說了一個 zset 跳表
用過 Redis 的哪些數據結構, 分別用在什么場景?
Java 初始化一個線程池有哪些參數可以配置, 分別是什么作用?
自己寫的 Java 應用調優(yōu)過哪些 JVM 參數, 為什么這么調優(yōu)?這個問住了,我只知道最大堆最小堆,開 G1,開 GC 日志以及 OOM dumper 這些基本的
用 Jetty 的時候有沒有配什么參數, 為什么這么配?
Jetty QTP 等待隊列配置成無限的話, 你覺得好嗎? 會有什么問題嗎?
用過 Linux Bash 里的哪些命令, 分別用它們干嘛?
一道筆試題: 需要在給的鏈接中作答, 不能 google, 不能跳出, 不能用 IDE:
啟動兩個線程, 一個輸出 1,3,5,7…99, 另一個輸出 2,4,6,8…100 最后 STDOUT 中按序輸出 1,2,3,4,5…100
三面
依然先聊項目
對監(jiān)控警報的項目很感興趣, 問了挺多細節(jié), 最后問了一個問題: 現在要你實現一個語義不弱于 PromQL 的查詢語言, 你能實現嗎?
這里雖然看過一些 Prometheus 的代碼,但其實對 PromQL 的 lexer 和 parser 部分沒有細看,還好之前因為數據同步項目里想寫聲明式 Stream SQL 研究過一點 ANTLR,用 ANTLR 寫語法 + AST 遍歷塞查詢邏輯給糊弄過去了。
問我覺得做得最深入的項目是什么, 當然是數據同步(狗頭)
聊數據同步項目(這個很符合我的預期,哈哈哈哈)
問 Linux 掌握得怎么樣?
沒有系統(tǒng)學習過,基本上是自己運維踩坑積累的
問 Golang 掌握得怎么樣?
用了半年, 看過 effective go
問算法掌握得怎么樣?到圖為止都可以
問最短路算法
只記得 dijkstra 了,描述了代碼流程
k8s 掌握得怎么樣?不怎么樣,沒有自己寫過 controller 和 scheduler,但是對概念都很熟悉,看過 xxx 這幾部分的源碼
k8s 的 exec 是怎么實現的?這個問題正中下懷,之前寫了 PingCAP 的小作業(yè)正好對這塊特別熟悉
四面
介紹一下自己
覺得自己基礎知識掌握怎么樣
平時一般會用到哪些數據結構?
鏈表和數組相比, 有什么優(yōu)劣?
如何判斷兩個無環(huán)單鏈表有沒有交叉點
如何判斷兩個有環(huán)單鏈表有沒有交叉點
如何判斷一個單鏈表有沒有環(huán), 并找出入環(huán)點
TCP 和 UDP 有什么區(qū)別?
描述一下 TCP 四次揮手的過程中
TCP 有哪些狀態(tài)
TCP 的 LISTEN 狀態(tài)是什么
TCP 的 CLOSE_WAIT 狀態(tài)是什么
建立一個 socket 連接要經過哪些步驟
常見的 HTTP 狀態(tài)碼有哪些
301和302有什么區(qū)別
504和500有什么區(qū)別
HTTPS 和 HTTP 有什么區(qū)別
寫一個算法題: 手寫快排
五面
介紹一下自己
在 k8s 上做過哪些二次開發(fā)?
自己用 Helm 構建過 chart 嗎?有哪些?
有沒有考慮過自己封裝一個面向研發(fā)的 PaaS 平臺?
配置中心做了什么?
為什么不用 zookeeper?
配置中心如何保證一致性?
Spring 里用了單例 Bean, 怎么保證訪問 Bean 字段時的并發(fā)安全?
用并發(fā)安全的數據結構,比如 ConcurrentHashMap;或者加互斥鎖
假如我還想隔離兩個線程的數據, 怎么辦?ThreadLocal,然后舉了個例子
Golang 里的逃逸分析是什么?怎么避免內存逃逸?這個不知道,認慫了
對比一下 Golang 和 Java 的 GC,答了一下 CMS、G1和三色標記,我對比的點是 JVM 有分代回收,Go 的 Runtime 沒有,沒能深入地講
Golang 的 GC 觸發(fā)時機是什么?閾值觸發(fā);主動觸發(fā);兩分鐘定時觸發(fā);
有沒有寫過 k8s 的 Operator 或 Controller?(我:沒有寫過)
談一談你對微服務架構的理解大體思路”微服務本質是人員組織架構演進與關注點分離”
談一談你對 Serveless 的理解,大體思路”Serveless 是繼 docker 與容器編排之后的又一次應用開發(fā)與基礎設施提供方之間的邊界劃分”
你認為 Serveless 是未來嗎? 為什么?大體思路”是云服務的未來,把蛋糕從企業(yè)的IT、運維與中間件部門切走,形成規(guī)模效應,做得越多賺得越多;公司內的話 servless 能夠幫助加速前臺業(yè)務迭代,但對中后臺的收益還看不到,未來可能會有比 servless 更適合中后臺的架構”
最后你有什么要問我的?我:為什么足足安排了五輪技術面,而且其中有兩輪似乎和 k8s 沒有關系啊?面試官:我們覺得你做過的東西挺多的,各個方向都想讓你嘗試一下 (我的內心:……)我:那這輪是最后一輪技術面嗎?面試官:不一定(我的內心:……)
后續(xù)還問了面試官一些業(yè)務相關的問題,就不贅述了
六面
問經歷
為什么要考慮出來看看呢?金句:”現在自己的技術成長有點碰到瓶頸,加上一直對您公司欽慕有加??””
現在公司的主營業(yè)務是什么?(這塊往技術上問了很多,感覺是想考察我解釋復雜問題的能力)
現在帶人嗎?report 層級是怎樣的?
對自己這幾年的經歷滿意嗎?
覺得自己有什么缺點?
碰到過什么很挫敗的事情嗎?
未來的職業(yè)規(guī)劃是怎樣的?
看機會的時候,主要考慮的是待遇、平臺、人員還是什么其他因素?
現在的待遇如何
有什么想問我的
小結
面試難度:正常
面試體驗:正常
問題偏向:基礎知識,開發(fā)常識,技術見解
面試前
問項目,抓出一些你擅長的領域或場景
問系統(tǒng)設計題,每題都會不斷深化需求讓你應變和權衡
問一道算法題(不難不偏),先看思路,再要求寫一下偽代碼看邊界條件能不能一次過
一面
介紹一下自己, 為什么選擇出來看看機會
聊項目, 警報怎么做的, 統(tǒng)一接入監(jiān)控項怎么做的
聊項目, 配置中心項目, 問實時配置推送怎么做
討論為什么選擇所有的組件依賴放在配置中心中控制
我現在要做一個限流功能, 怎么做?令牌桶這個限流要做成分布式的, 怎么做?令牌桶維護到 Redis 里,每個實例起一個線程搶鎖,搶到鎖的負責定時放令牌
怎么搶鎖?Redis setnx, 鎖怎么釋放?搶到鎖后設置過期時間,線程本身退出時主動釋放鎖,假如線程卡住了,鎖過期那么其它線程可以繼續(xù)搶占,加了超時之后有沒有可能在沒有釋放的情況下, 被人搶走鎖,有可能,單次處理時間過長,鎖泄露,怎么解決?
換 zk,用心跳解決,不用 zk 的心跳, 可以怎么解決這個問題呢?
每次更新過期時間時,Redis 用 MULTI 做 check-and-set 檢查更新時間是否被其他線程修改了,假如被修改了,說明鎖已經被搶走,放棄這把鎖
假如這個限流希望做成可配置的, 需要有一個后臺管理系統(tǒng)隨意對某個 api 配置全局流量, 怎么做?
在 Redis 里存儲每個 API 的令牌桶 key,假如存在這個 key,則需要按上述邏輯進行限流
某一個業(yè)務中現在需要生成全局唯一的遞增 ID, 并發(fā)量非常大, 怎么做
snowflake (這個其實答得不好,snowflake 無法實現全局遞增,只能實現全局唯一,單機遞增,面試結束后就想到了類似 TDDL 那樣一次取一個 ID 段,放在本地慢慢分配的策略)
算法題, M*N 橫向縱向均遞增的矩陣找指定數, 只想到 O(M+N)的解法 補充: 這幾天刷 leetcode 碰到這題了, 240. Search a 2D Matrix II. 辦法是從左下角或右下角開始查找.
有什么想問我的?限流,分布式鎖,UUID 都屬于后端的經典面試題,這輪面試的參考價值挺大的。
二面
平時用的工具鏈和技術棧是什么
golang 踩過坑嗎?答了之前 PingCAP 面試時面試官問的 for-range 里的 go-routine 閉包捕獲問題,這段 golang 代碼有沒有 bug(還是一個 for-range 的坑), 有 bug,for-range 的 value 引用拷貝問題
Java 中 HashMap 的存儲, 沖突, 擴容, 并發(fā)訪問分別是怎么解決的, Hash 表,拉鏈法(長度大于8變形為紅黑樹),擴容*2 rehash,并發(fā)訪問不安全, 拉鏈法中鏈表過長時變形為紅黑樹有什么優(yōu)缺點?優(yōu)點:O(LogN) 的讀取速度更快;缺點:插入時有 Overhead,O(LogN) 插入,旋轉維護平衡
HashMap 的并發(fā)不安全體現在哪?拉鏈法解決沖突,插入鏈表時不安全,并發(fā)操作可能導致另一個插入失效,
HashMap 在擴容時, 對讀寫操作有什么特殊處理?不知道
ConcurrentHashMap 是怎么做到并發(fā)安全的?
segment 分段鎖
Java 有哪些鎖機制, 分別有什么特點?
Synchronized、可重入鎖
知道 CAS 嗎? Java 中 CAS 是怎么實現的?Compare and Swap,一種樂觀鎖的實現,可以稱為”無鎖”(lock-free),CAS 由于要保證原子性無法由 JVM 本身實現,需要調用對應 OS 的指令(這塊其實我不了解細節(jié))
MySQL 的存儲引擎用的是什么?(InnoDB)為什么選 InnoDB?幾乎所有公司用 MySQL 都用 InnoDB,降低踩坑成本;聚簇索引,MVCC
MySQL 的聚簇索引和非聚簇索引有什么區(qū)別?
聚簇索引的葉子節(jié)點是數據節(jié)點(比如定義了主鍵時的主鍵索引),非聚簇索引葉子節(jié)點是指向數據塊的指針
B+樹和二叉樹有什么區(qū)別和優(yōu)劣?B+樹是多叉樹,深度更小,B+樹可以對葉子節(jié)點進行順序遍歷,B+樹能夠更好地利用磁盤扇區(qū);二叉樹:實現簡單
針對一個場景設計索引,具體場景忘記了,反正考察的是聯合索引與列選擇性的知識
現有一個新的查詢場景, 要怎么解決?假如要查 A in () AND B in (), 怎么建索引?
只給選擇性高的一列建索引,這里因為兩個都是范圍查詢所以另一個是走不到索引的(這里答的不好,其實也可以建聯合索引然后用 (A,B) in ((1,2),(3,4)) 的方式去查)
查 A in () AND B in () 時, MySQL 是怎么利用索引的?
先走一個非聚簇索引,查詢出行數據后再用另一列回表做篩選
假如查詢 A in (), MySQL 是針對 N 個值分別查一次索引, 還是有更好的操作?不知道,有了解的同學可以留言 (補充, @BillyLu 貼出了文檔 equality-range-optimization, 大意是對非唯一索引 MySQL 會使用 index dive 的方式估算這個 range index 涉及的行數, 結合where optimization 中說明的在走 index 時假如涉及行數過多會走 full table scan, 那么假如 estimation 認為這次 IN 不夠好, 是會走全表掃描的. 不知道除此之外, 面試官還有沒有想考察的點)
用過 Redis 的哪幾種數據結構? (都用過) ZSET 是怎么實現的?跳表
zrange start, stop, 總長度為 n, 復雜度是多少?O(logN) (答得不好,實際是 O(M+log(N)), M 是結果集基數 stop-start)
Kafka 的消費者如何做消息去重?
MySQL 去重、Redis 去重、假如場景量極大且允許誤判,布隆過濾器也可以
介紹一下 Kafka 的 ConsumerGroup挺長的,略
Kubernetes 和 Docker 用得怎么樣? (我:在公司推行布道)給它們貢獻過代碼嗎?(我:沒有…)
時序型數據庫的存儲結構是怎么樣的?
講了 prometheus 1.x 和 2.x 的存儲結構
LSM 樹了解嗎? 是一種什么存儲結構?
Log-Structured Merge Tree,犧牲讀性能換取性能,RocksDB、HBase、Cassandra 都在用,結構有點忘了,只說了先寫 memtable 再刷盤成 sstable
在生產中用過 Cassandra 和 RocksDB 嗎? 量有多大?用過,Cassandra 存調用鏈,RocksDB 做 flink 和 Kafka Stream 的本地狀態(tài)存儲
Cassandra 的墓碑機制是什么?不知道,對 Cassandra 停留在使用階段
三面
聊項目和工作經驗
用 Kubernetes 的過程中踩過哪些坑?
考慮一個業(yè)務場景: 頭條的文章的評論量非常大, 比如說一篇熱門文章就有幾百萬的評論, 設計一個后端服務, 實現評論的時序展示與分頁我: 需不需要支持頁碼直接跳轉?面試官: 支持和不支持兩種場景都考慮一下我: 不需要支持頁碼翻頁就傳評論 id 用 offset 翻頁
假如用 id 翻頁的方式, 數據庫表如何設計? 索引如何設計?(文章id, 評論id) 建聯合索引,評論 id 需遞增,
假如量很大, 你覺得需要分庫分表嗎? 怎么分?需要分,分表有個權衡,按文章 id 分表,讀邏輯簡單,但寫有熱點問題;按評論 id 分表,讀邏輯復雜,但寫壓力就平均了。寫是要首先保證的,而讀總是有緩存等方案來折中,因此按評論 id 分表好。
分庫分表后怎么查詢分頁?每張表查 N 條數據由 client 或 proxy merge
分庫分表后怎么保證主鍵仍然是遞增的?講了 TDDL 的辦法:有一張專門用于分配主鍵的表,每次用樂觀鎖的方式嘗試去取一批主鍵過來分配,假如樂觀鎖失敗就重試
現在需要支持深分頁, 頁碼直接跳轉, 怎么實現?不能做精準深分頁,否則壓力太大,找產品進行妥協(xié),在50或100頁后數據分頁是否可以不完全精確,假如可以,那么緩存深頁碼的起始評論 id
瞬時寫入量很大可能會打掛存儲, 怎么保護?斷路器
斷路器內部怎么實現的?可以用 ringbuffer
斷路器會造成寫入失敗, 假如我們不允許寫入失敗呢?
先寫進消息隊列,削峰填谷異步落庫
算法題: N 場演唱會, 以 [{startTime, endTime}…] 的形式給出, 計算出最多能聽幾場演唱會,先講了思路, 按 endTime 升序排列,再順序取最多場次,(講完思路之后)屏幕共享給我, 用你最熟悉的語言把這個算法實現,用 go 實現了一版
你用了貪心法, 貪心可能會存在什么問題?局部最優(yōu),在這個問題里,只能找到一個可能解,無法找到所有排列方式
HR 面
小結
面試難度:正常
面試體驗:挺好
問題偏向:架構設計,算法
簡歷里寫了的項目,以及熟練程度在”掌握”以上的領域與中間件要好好準備,當面試官問你一個偏門的問題時,他內心其實也沒希望你能答上來。而當面試官問你簡歷上涉及的問題時,假如你答不上來,那面試官就覺得這個人要么是眼界太低,會了一點就覺得自己掌握了,要么是簡歷造假在胡吹,這兩種都非常不利;
在上一條的基礎上,可以準備一個最得意的項目,在簡歷上和面試過程中引導面試官往這塊聊;
面試前心里可以準備一個方法論:明確面試官想招怎樣的人有哪些特質,在面試過程中努力表現出這些特質。這聽起來是句正確的廢話,但面試的過程不可控因素太多,有一個清晰的目標在腦子里能幫你在手足無措時想到說什么。舉個例子,有一輪中面試官問我有什么問題時,我就問貴司的對應崗位會面臨哪些技術挑戰(zhàn)(當然要先說清楚這不是在質疑他們沒有挑戰(zhàn),只是自己渴望挑戰(zhàn));
System Design Primer,入門架構設計必看的一篇資料。看完之后提醒自己始終記得:架構設計的本質是深入理解業(yè)務場景之后用工程經驗做出最佳權衡。面試時的一個套路是先提綱挈領地把舍棄什么來換取什么講明白;
云原生相關,Kubernetes Concepts 部分建議再看一遍,源碼部分推薦看 apiserver 中的 CRD 部分與 aggregation layer、kubelet 的 pod 狀態(tài)同步、scheduler 的調度部分以及Sample Controller 如何寫一個自己的 controller
語言方面,推薦看書《Effective Go》《Effective Java》,都很薄。這兩本書我是以前看的,面試前沒有專門準備語言相關;
算法相關,這部分我純鶸,說實話我覺得大學里那本教材《數據結構與算法分析》就寫得很不錯…至于 leetcode,面試前沒有刷過,最近為了練習 Rust 刷了60多題,并沒有碰到面試里出現過的題目,看起來要刷 leetcode 的話就得走量多刷點,刷的少純拼強運了;
Golang for range 的坑 有兩輪面試都涉及到了這個話題,這里貼一下;






關注Java技術棧看更多干貨


