面試經驗分享 - Dcard 公司的 Web Backend Intern 面試
這篇文章距離我錄取 Dcard 的 Web Backend Intern 有一兩個月的時間了 XD 只是一直沒有時間寫分享文,因為 7/6 就要去上班了,所以特來發此分享文紀錄一下。
其實我投了許多知名的外商公司的 Intern 加一間本土公司的 Dcard,然而外商公司只有到繳交履歷的階段,連面試都沒上真的是很慘 QQ,雖然我也沒有說很意外,因為知名外商公司一向都很搶手,而且許多強者真的是太強了,我自認為我還是很 junior 的工程師 XD。但因為為了生活還是要想辦法找到一份工作,才能半工半讀阿 XD
所以,也很感謝在面試 Dcard 的時候都很順利,也能夠拿到此機會,讓我能夠一探 Dcard 的系統架構。以下的內容我會分享在 Dcard 面試的題目,以及我大致上的應對方式。
面試流程
我是應徵 Dcard 2020 年開放的 Web Backend Intern,當初還有看到前端及資料分析的實習生的招募,但有在看我 Blog 的文章就知道,我是完全怨恨前端的 XDD,沒辦法我對前端完全沒有愛,老實說我覺得天分跟喜好都有影響,我喜歡分析後端的架構,對於視覺呈現的東西我真的是完全不感興趣就是了。
在面試流程上可以看成是有四關的:
-
作業關
在面試之前,Dcard 在徵才網站上有說明需要繳交作業,簡單來說就是要你寫一個 Project,而 Project 的內容是要實作一個 middleware 來計算 IP 次數的功能,藉此來限制流量。這邊我記得是沒有特別說限制的語言及資料庫,完全自由發揮。在後面會再詳細說明~
-
技術關
這關顧名思義,就是 Dcard 的後端工程師來面試,所以會問的就是技術上的問題,至於有那些問題,在後面會詳細列出來~
-
執行長聊天關 (?)
這關說實在可以當作是跟執行長聊天吧,因為我去面試的時候,Dcard 執行長是直接問我有甚麼問題,這個我在之前看到別人的 Dcard 面試經驗分享也有看過,所以我算是事先就有準備一些問題,之後在後面也會詳細列出來。
-
HR 聊天關 (?)
這個相較於前面兩關就會在更輕鬆一點,因為 HR 滿親切的,沒有看到那種很嚴肅的 HR,所以也可以看成是聊天的感覺,然後 HR 也是有問一些問題,之後在後面也會詳細列出來。
作業關面試分享
講真的,我之前應徵的實習工作都沒有要上傳作業的,不過也有可能我的公司都很小,不然就是他們對實習生的要求不高就是了。
以下是 Dcard 作業題目描述:
Dcard 每天午夜都有大量使用者湧入抽卡,為了不讓伺服器過載,請設計一個 middleware:
- 限制每小時來自同一個 IP 的請求數量不得超過 1000
- 在 response headers 中加入剩餘的請求數量 (X-RateLimit-Remaining) 以及 rate limit 歸零的時間 (X-RateLimit-Reset)
- 如果超過限制的話就回傳 429 (Too Many Requests)
- 可以使用各種資料庫達成
這個題目算是很常見的,也算是最基礎的限制流量的方式,這邊因為我覺得只寫一個 middleware 有點難以 Demo,所以我索性寫了一個很小型 Dcard 系統的 Backend,但是也只是有一些註冊登入使用者、抽卡等 API 而已。因為我個人是滿好奇 Dcard 後端是怎麼去實作抽卡這個步驟的,所以就順便做個陽春版了~然後在抽卡 API 上前面放前面作業所規定的 middleware。
這邊詳細作業的實作架構就不多講了,因為可以直接參考我的 GitHub:https://github.com/KennyChenFight/dcard-simple-demo
我在 README 寫的算滿詳細的,這邊就只講我大致上的思路就好:
-
middleware 部分應該搭配類似於 Redis 類型的 DB
這種功能一般情況下是不會搭配如 PostgreSQL 這類型的 RDBMS 的,簡單來說 Redis 存放這些資料,就如同存 Cache 資料,因為每個 User 的 IP 記數,主資料庫根本就沒必要知道這件事情,主資料庫本就應該負責真正重要的資料,如果讓這類型的 middleware 搭配主資料庫將會大幅度拖垮效能,也就是在大部分的情況下,我們都應該先去快取資料庫取資料,因為這樣的存取或寫入的速度快,只有當快取資料庫取不到相對應的資料,才會去取主資料庫的資料。
-
熟悉何謂 Race Condition
不管是 RDBMS 或 NoSQL 都會遇到 Race Condition,也就是我在實作的時候,如果你不瞭解 Redis 的機制,那也是會容易寫出有 Race Condition 的,這邊我算是有寫出兩種版本,一種是 Race Condition,一種是沒有的,因為說實在的 IP 記數那邊少記了一次或多記了一次,影響很大嗎?
我的想法是:如果系統並沒有高流量,即使使用者會多拜訪個幾次,對於系統負擔造成不是很大,採用簡單的實作方式即可,即便會 Race Condition。而沒有 Race Condition 的版本,需要撰寫 Lua 腳本才對 Redis 進行存取跟寫入的動作,對工程師而言,你需要多學一個 Lua 語言,你才能維護存取跟寫入的動作,當然這是沒有很難,如果想知道為什麼可以去參考我的 GitHub。我後來是丟沒有 Race Condition 的版本,不過我在技術關的時候有講解有這兩種版本以及採用情境當下為何。
作業差不多就是這樣,然後因為沒有特定限制語言及資料庫,但是在徵才說明上,有特別說希望是熟悉 Golang 或 Node.JS,而資料庫的部分希望熟悉 PostgreSQL 及 MongoDB,因此作業我就是採用 Golang+PostgreSQL+Redis 來實現的。
不過,題外話,我到現在還是不敢說熟悉某種程式語言,我只能說認識,我對熟悉的定義是非常專精並且了解程式語言整個底層架構 XDD
還在學習中就是了 ><
技術關面試分享
這個 Dcard 的技術關,其實跟我以前面試的公司不一樣,因為我以前應徵的都是實習生的職位,說實在面試的時候根本就不會問甚麼技術的問題,就算有,也沒有很細,不過也有可能我遇到的公司都很水吧 XD
相較起來,會覺得 Dcard 的技術關相對較硬,如果你是超級超級 junior 後端,在這邊很容易會被問倒。而且因為我事先不知道會被問這樣,我事前也是沒有任何準備 XD 不過好佳在憑藉著平常有在做筆記及工作的關係,有一些技術的東西根本就會深刻在腦海中。
再來要補充的就是這關由於疫情的關係所以是視訊面試,我覺得這也因此對我有好處吧,因為我個人其實滿容易緊張的,但是視訊面試的話我是不太會緊繃的,而且很自在。
以下是被問到技術題:
-
作業講解
這個我有點忘了,但是我記得好像是有問作業上的架構思路講解,我大部分就是講為什麼要用 Redis,以及如何用 Redis 實作該 middleware,還有如何避免 Race Condition,但我這邊很強調 RDBMS 跟 NoSQL 的使用情境。
-
RDBMS 與 NoSQL 的選用考量
這題我個人認為是因為我的作業講解很強調 RDBMS 跟 NoSQL 的情境,所以這邊特地問我的選用考量,我以前的觀念是用 NoSQL 好爽,schema 亂開且很有彈性,想改就改。直到我的專案因為用了 MongoDB 當主資料庫,並且當專案規模越來越大時,我才發現有夠痛苦,我還是想強調就是,該專案不管未來是否會有高流量的情況產生,都還是需要用 RDBMS 作為資料庫,因為大部分的系統的功能時做下來,都會造成有多種 JOIN 的情況,如果你使用 NoSQL 會變成多文檔的 JOIN 方式,要知道 MongoDB 是只有支持單文檔事務的,如果你要支持多文檔的事務,你必須自行實作 two phase commit,雖然官方有提供程式碼,可是要知道這段程式碼可是又臭又長,而且並不能 100% 保證不會出錯。雖然我知道現在 MongoDB 4.0 之後貌似有支援多文檔事務,這方面我還沒有很實際去了解。
當然會有人說 NoSQL 設計上,就應該把 JOIN 的情況改成單文檔的方式,然後不斷地內嵌文檔,這樣就不會有多文檔 JOIN 的方式產生,這個我個人認為整個 Schema 會變得很複雜,而且在程式上存取的撰寫並沒有很容易,反之很容易會出錯,而且需求多變,你要利用單文檔打遍天下,我個人是覺得很困難。而且 MongoDB 我出現過遺失資料的情況…QQ
我是覺得高流量的系統應該是由 RDBMS 跟 NoSQL 撐起的,兩者是互相輔助的功能,所以一個好的系統不應該只靠 NoSQL 打天下。
-
RDBMS 的隔離層級所造成的 Race Condition
RDBMS 的 Race Condition 我相信是一個後端工程師需要理解的概念,我之前為了理解這個也做了不少壓力測試的實驗,為的就是看到各種 Race Condition 的情況。
不過說真的有點漏氣,當時回答的時候有一些 Race Condition 的專有名詞忘記了,所以並沒有講得很詳細,最基本的當然就是 Dirty Read、Non-repeateable Read、Phantom Read,然後如何解決這些 Race Condition,除了透過設置 RDBMS 的隔離層級還有就是在 SQL 語句上做手腳,
以上這些解決方法都有在我的 Blog 文章提到,可以尋找 RDBMS 分類就可以看到了 XD
-
Golang channel 的解釋
這邊就偏向講解 Golang 程式語言的概念了,要寫多 Goroutine 的程式,Channel 的概念是必須要懂得。
-
當有失敗的 Goroutine,如何去處理
這邊是問一種情境,如果你的 Goroutine 可能遇到 Error 而被關閉了,你要怎麼知道得知這件事情,這種需求我個人認為最普遍的方式就是透過 Channel 來進行通知寫下 log,以方便日後能夠發現及 Debug。
-
Redis 選用的 key value 架構選用考量
這邊的話面試官沒有給任何情境,所以我也就是拿作業的實作方式,講解存入 Redis 是用哪種資料型態,並且為何這樣做及如何存取,這邊的話就是講解 Redis 的 Hash 資料結構
-
RDBMS 的 Index 是甚麼,如何輔助
這邊就是講 RDBMS 的索引是甚麼意思,又要怎樣才能建立好的索引,提升效能等事情,不過個人並沒有對這個很拿手,應該說理解了基本概念,可是真的要熟悉是需要一些實戰經驗的累積的。
-
如何測試 SQL 語句效能好不好
這邊我猜面試官是想要考知不知道 EXPLAIN 語句,因為每個查詢語句都會建立一個每個查詢設計一個查詢計劃,透過看這個查詢計畫可以看出該 SQL 語句是慢在哪裡,透過這樣的方式去改進 SQL 語句的效能。
-
考你一個 SQL 語句,問你哪些欄位可以加 index
1
select id, title from posts where pinned = true and createdAt > '2019-04-23'
這邊是考說如果有該 SQL 語句,你會把索引加在哪個欄位上。
-
Message Queue 的 Consumer 怎麼處理 fail data 或是 Consumer 掛了怎麼辦
這邊會問我這個問題,是因為我在前公司負責做有關 Message Queue 應用的專案,所以特定問我是如何處理失敗的資料或者 Consumer 掛了的話要如何重啟或是解決方式。
其實對此我有寫了一個 RabbitMQ 封裝的 Library,可以參考一下:https://github.com/KennyChenFight/rabbitmq-go
雖然封裝的普普通通,但也是有完成重新連線的機制,歡迎發 issue 一起改進,有空我也會持續改善架構的。
-
CI/CD 的概念
講真的我 CI/CD 用的並不多,主要原因是我之前的工作經驗,公司沒有很扎實的 CI/CD 的流程,其實也可能是因為我是實習生的職位,我根本碰不到這個,大部分的工作專案大多是一人完成,也根本沒有協作的經驗,很多情況下我都是透過自學或者是跟朋友寫專案慢慢去摸索的,對我來說目前比較熟悉的話大概就是 GitLab 提供的 CI/CD 的功能了~
-
Docker 的概念
這個也算是老生常談了,現在很多公司都在用 Docker 了,不管是開發或是上線,都是非常好用的工具。
-
問你想問面試官什麼問題、為什麼想來 Dcard
這個題目就很常見了,我記得我就是問了 Dcard 系統的架構及解釋為什麼我想要換工作並應徵 Dcard。講白了就是我想體驗團隊協作、完整的 CI/CD、Code Review、高流量的設計。原因就是這麼簡單,我覺得當經歷過這些,整個視野才會提高,而且就很清楚理解業界是怎麼運作的。
執行長關面試分享
其實純粹聊天的面試才是我最害怕的 XD 因為可能一不小心就被面試官心裡打了個大 XX 都不知道 QQ 尤其是如果是自己提問題的話又更加困難,總之這關我倒是聊了滿多創業的事情的,畢竟曾經我也想要創業,然而面對現實還是先擱著了 QQ
我只能說年紀輕輕就成立公司是一件很大膽、勇氣的事情,能夠做出自己喜歡的產品是一件很有成就感的事情,Dcard 到了今天的規模,雖然受眾大多是台灣的大學生,但這也足以說嘴了,而且當你用戶越多,寫出來的系統就會越被挑戰,當越被挑戰就需要花很多時間去改進,工程師實力才會大幅度的提升。所以如果想要體驗高流量,要先想辦法提高用戶,否則高流量的一切架構設計都是白談的。
HR 關面試分享
這關就很輕鬆了,HR 大致上就是問我為什麼會喜歡寫程式,為什麼要換掉前一份工作來應徵 Dcard,還有自己作品分享等經驗,就盡量分享自己的經驗及思路就可以了,有時候我都會陷入擠不出問題,然後就乾在那邊 QQ 我覺得這也是我需要改進的地方,不過我是覺得當問題都問完之後就也不必硬聊,可以提早結束就好。
總結
以上大概就是 Dcard 面試過程的分享,說實在很多都是第一次被問到,也算是給了我一個審視自己的機會,我個人覺得 Dcard 對於實習生的標準是一點都不馬虎的,而且感覺在整個專案流程上是做得很完善的,在我之後進去工作後,會在分享自己的感想,總而言之,我覺得進去 Dcard 是一種挑戰,而且我相信強者一堆,我會被電爆,所以像個海綿一樣努力汲取吧!
最後最後!請聽我一言!
如果你還沒有註冊 Like Coin,你可以在文章最下方看到 Like 的按鈕,點下去後即可申請帳號,透過申請帳號後可以幫我的文章按下 Like,而 Like 最多可以點五次,而你不用付出任何一塊錢,就能給我寫這篇文章的最大的回饋!