如果說很多公司的面試是在考「你會不會寫這道題」,Snowflake 更像是在考「你能不能把一個系統從頭到尾做扎實」。這篇按 完整 loop 走一遍:從兩輪電話面試到四輪 Virtual Onsite,逐輪說清楚考什麼、面試官盯哪裡,以及一條反覆出現的主線——工程完整性(engineering completeness)。每道題只做輕量拆解,把更多篇幅留給最能拉開差距的 系統設計輪備考。Infra / 資料基礎設施方向的同學尤其值得對號入座。
一、全流程速覽
Snowflake 的軟體工程師 loop 由 兩輪電面 + 四輪 Onsite 組成,節奏緊湊、評分細緻。先用一張表建立整體印象:
| 階段 | 輪次 | 時長 | 內容 | 側重 |
|---|---|---|---|---|
| 電面 R1 | 純 coding | 1h | LRU Cache(Data Infra 團隊) | O(1) 實作 + 指標操作細節 |
| 電面 R2 | 純 coding | 1h | Range Module(線段樹簡化版) | 區間合併 + corner case |
| Onsite R1 | coding | 1h | 滑動視窗眾數 | 高效更新,不重掃視窗 |
| Onsite R2 | coding | 1h | 帶頻次的區間合併 | line sweep + 邊界定義 |
| Onsite R3 | BQ | 1h | 分歧 / 技術權衡 | 模糊情境下的判斷力 |
| Onsite R4 | system design | 1h | Log Ingestion Service | Infra 落地到實作細節 |
一條貫穿始終的評分線:面試官不滿足於「跑得動」,他們要看你有沒有主動涵蓋邊界、能不能講清楚資料結構選型的理由。 這就是 Snowflake 的 Infra 味道。
二、電面 R1:LRU Cache(輕量拆解)
第一輪由 Data Infra 團隊的面試官出題,人很隨和,題目是經典的 LRU Cache:實作 get 和 put,兩者都要 O(1)。
思路只有兩句話:雜湊表做 O(1) 查找,雙向鏈結串列維護存取順序。 每次存取就把節點挪到串列頭,容量滿了就刪尾節點。面試官真正盯的是 節點更新邏輯和刪除時的指標操作——先斷鏈再接鏈、別丟參照,這一段是評分點。
class Node:
def __init__(self, key=0, val=0):
self.key, self.val = key, val
self.prev = self.next = None
class LRUCache:
def __init__(self, capacity: int):
self.cap = capacity
self.map = {} # key -> Node
# 哨兵節點:head 之後是最近使用,tail 之前是最久未用
self.head, self.tail = Node(), Node()
self.head.next, self.tail.prev = self.tail, self.head
def _remove(self, node):
node.prev.next, node.next.prev = node.next, node.prev
def _add_front(self, node):
node.prev, node.next = self.head, self.head.next
self.head.next.prev = node
self.head.next = node
def get(self, key: int) -> int:
if key not in self.map:
return -1
node = self.map[key]
self._remove(node) # 先摘下
self._add_front(node) # 再放到最前
return node.val
def put(self, key: int, value: int) -> None:
if key in self.map:
self._remove(self.map[key])
node = Node(key, value)
self.map[key] = node
self._add_front(node)
if len(self.map) > self.cap:
lru = self.tail.prev # 最久未用
self._remove(lru)
del self.map[lru.key]
時間複雜度:get / put 均 O(1);空間複雜度:O(capacity)。
三、電面 R2:Range Module(輕量拆解)
第二輪是 Range Module,可以理解成線段樹的簡化版:實作 addRange、queryRange、removeRange 三個操作,維護一組不相交區間。
用 TreeMap(有序映射)存區間是最順的做法:插入時向左右探鄰區間做合併,刪除時可能把一個區間 拆成兩段。面試官會追問 TreeMap 各操作的複雜度,以及兩個高頻 corner case:插入時與既有區間重疊、刪除時正好落在區間中間。Python 沒有內建 TreeMap,用 sortedcontainers.SortedDict 表達同樣的語意即可,面試口頭講清「向左右 floor / ceiling 查找鄰居」是關鍵。
討論重點:把「合併」和「拆分」兩條路徑分別講透,主動報出重疊、包含、相鄰三種關係的處理,比悶頭寫完更能拿分。
四、Onsite R1:滑動視窗眾數(含完整程式碼)
給定整數陣列和視窗大小 k,回傳每個視窗內出現次數最多的元素。要求高效,不能每次重掃整個視窗。
思路:雜湊表記頻次 + 最大堆積取眾數,堆積裡存的是「頻次快照」,用 懶刪除 跳過過期項——這正是面試官反覆追問的點:怎麼高效處理已經不在視窗裡的元素。
import heapq
from collections import defaultdict
def sliding_window_most_frequent(nums, k):
freq = defaultdict(int)
heap = [] # (-count, value) 最大堆積
res = []
for i, x in enumerate(nums):
freq[x] += 1
heapq.heappush(heap, (-freq[x], x)) # 推入當前頻次快照
if i >= k - 1:
# 懶刪除:堆頂快照與真實頻次不符就丟棄
while -heap[0][0] != freq[heap[0][1]]:
heapq.heappop(heap)
res.append(heap[0][1])
left = nums[i - k + 1] # 移出視窗最左元素
freq[left] -= 1
return res
# 快速自測
if __name__ == "__main__":
print(sliding_window_most_frequent([1, 3, 3, 2, 1, 1], 3)) # [3, 3, 1, 1]
討論重點:為什麼不每視窗重建堆積(O(nk)),而用懶刪除均攤;堆積裡可能堆積過期項,但每項最多被彈出一次,整體可控。時間複雜度:O(n log n);空間複雜度:O(n)。
五、Onsite R2:帶頻次的區間合併(輕量拆解)
區間可能重疊多次,要輸出合併後的區間 以及每段的頻次。
思路是 line sweep:把每個區間拆成起點(+1)和終點(−1)事件,排序後掃描,維護當前活躍計數即為該段頻次。真正的坑在 邊界定義:起點和終點落在同一時間點誰先處理、區間是否 inclusive——這兩點必須在寫之前和面試官對齊。
def merge_intervals_with_freq(intervals):
events = []
for s, e in intervals:
events.append((s, 1)) # 進入:頻次 +1
events.append((e, -1)) # 離開:頻次 -1
events.sort()
res, active, prev = [], 0, None
for pos, delta in events:
if prev is not None and pos > prev and active > 0:
res.append((prev, pos, active)) # [prev, pos) 段的頻次
active += delta
prev = pos
return res
討論重點:把 −1 與 +1 在同一座標上的排序順序講清楚(決定端點是否算重疊)。時間複雜度:O(n log n);空間複雜度:O(n)。
六、Onsite R3:BQ 輪速記
BQ 偏向 判斷力和協作,問題很典型:
- "Have you ever disagreed with a teammate, and how did you resolve it?"
- "Tell me about a time you made a technical tradeoff."
我講了一個非同步資料處理系統裡權衡 批次處理延遲 vs 資源使用率 的故事:為什麼在某個資料量級下選擇放大 batch、犧牲一點時延來換吞吐。Snowflake 很看重你能否在 模糊情境下給出有理由的判斷,而不是背標準答案。
七、Onsite R4:系統設計 —— Log Ingestion Service
設計一個簡化的日誌攝取服務,支援高吞吐寫入、持久化儲存,以及查詢最近 N 筆日誌。
這一輪最能體現 Snowflake 的 Infra 底色,面試官要的不是幾個高層的框,而是 能落到實作的具體方案:
| 層 | 選型 | 作用 |
|---|---|---|
| 接入 | Load Balancer | 分攤寫入壓力、水平擴展 |
| 緩衝 | Kafka / 自建 ring buffer | 削峰、解耦 ingest 與儲存 |
| 儲存 | S3(落盤) + RocksDB(索引) | 持久化 + 快速點查 |
| 查詢 | time-based index | 加速「最近 N 筆」檢索 |
面試官層層追問的 follow-up:日誌去重、亂序(out-of-order)處理、一致性(consistency)trade-off。整段對話考的是你對 系統瓶頸 的理解——寫入熱點在哪、索引會不會成為記憶體瓶頸、查詢延遲和一致性怎麼取捨。這一輪是全 loop 最能拉開差距的地方,下面單獨給一份備考清單。
八、如何專門備考系統設計輪
系統設計是 Snowflake(尤其 Infra)最看重、也最容易被裸考的一輪。按下面這幾條準備,方向會穩很多:
- 先對齊需求再動筆:寫 QPS / 資料量 / 延遲目標 / 一致性要求,把「簡化版」的邊界和面試官確認清楚,別預設。
- 每一層都要能下鑽到實作:不要停在「加個訊息佇列」,要能說清用 Kafka 還是 ring buffer、partition 怎麼切、offset 怎麼管。
- 主動拋 trade-off:去重(冪等寫 vs 事後 dedup)、亂序(浮水位 / 緩衝視窗)、一致性(最終一致 vs 強一致)——把選擇的理由講出來。
- 定位瓶頸:主動指出寫入熱點、索引膨脹、查詢扇出等瓶頸點,並給出緩解手段(分片、分層儲存、冷熱分離)。
- 畫出資料流:從一筆日誌進來到能被查到,端到端走一遍,比零散羅列元件更有說服力。
- 用真題限時演練:log ingestion、rate limiter、metrics pipeline 這類 Infra 題反覆推演到能脫口而出,必要時用 VO 輔助 / VO 代面 做真實節奏的對接演練。
九、總結:Snowflake 到底在考什麼
一句話——工程完整性 + 系統設計的 trade-off 表達。coding 題本身不算最難,但面試官會把邊界、指標、複雜度、選型理由問到底;系統設計則要求你落到實作、講清瓶頸。把 LRU / Range Module / 滑動視窗 / line sweep 練到能講清「為什麼這麼選」,再把系統設計輪準備成「Infra 落地版」,整個 loop 就穩了。
FAQ
Q1:Snowflake 完整面試流程是怎樣的?
兩輪電話面試(各 1 小時、純 coding)+ 四輪 Virtual Onsite(兩輪 coding + 一輪 BQ + 一輪 system design)。整體偏 Infra 方向,評分核心是工程實作的完整性。
Q2:Snowflake 的 coding 到底難不難?
題目(LRU、Range Module、滑動視窗、line sweep)難度中等偏上,但真正拉分的是細節:懶刪除如何跳過過期元素、TreeMap 各操作複雜度、區間刪除時的拆分、line sweep 端點排序,面試官都會追問到底。
Q3:系統設計輪最容易踩的坑是什麼?
停在高層框圖、不下鑽到實作。以 log ingestion 為例,要能展開 buffer(Kafka / ring buffer)、儲存(S3 + RocksDB)、索引(time-based),並主動討論去重、亂序、一致性的取捨,同時點出系統瓶頸。
Q4:這篇和另一篇 Snowflake Onsite 複盤有什麼區別?
那篇聚焦幾道題的深度解法;這篇走 完整 loop(電面到 Onsite 逐輪),每題輕量拆解,把重點放在 Snowflake 的工程完整性評分標準和系統設計輪的專項備考上,適合先建立全局視角。
Q5:怎麼高效準備 Snowflake VO?
把高頻資料結構題練到能講清選型理由,BQ 準備好「技術權衡」類故事,系統設計準備 Infra 落地版。需要真題限時陪練、系統設計一對一推演,或 VO 輔助 / VO 代面 的即時對接,可以發職位 JD 先做題型預測再排練習計畫。
正在準備 Snowflake 全流程面試?
Snowflake 考的是工程完整性 + Infra 系統設計 + trade-off 表達。oavoservice 提供 Snowflake / 資料基礎設施方向的 VO 全流程陪練:電面高頻題限時模擬、log ingestion 系統設計一對一推演、BQ 權衡故事打磨,也支援 VO 輔助 / VO 代面 的即時對接。教練含前大廠 Infra 工程師,熟悉 Snowflake「摳實作細節」的評分風格。
立即加入微信 Coding0201,取得 Snowflake 全流程真題與陪練。
聯絡方式
- 微信:Coding0201
- Email:[email protected]
- Telegram:@OAVOProxy