1. 程式人生 > >小林求職記(四)不會吧不會吧,面試還真會問這些呀

小林求職記(四)不會吧不會吧,面試還真會問這些呀

前傳

小林求職記(三)一上來就圍繞電商系統層層提問,我太難了....

經歷了好幾次求職失敗的經歷,小林最終找到了自己以前一起工作合作的老同事王哥,並向前請教面試技巧。

小林: 王哥,我最近面試了好幾家公司,但是面試都掛了,我覺得自己好多知識點似乎都學得不是很深入啊,自己都快“裂”開了啊。

王哥 :哦,你平時大多數時間都是怎麼學習的啊?會定期自己的做一些知識腦圖的梳理工作嗎?

小林 :啥,下班時間一般我都是很晚了,回到家也基本沒有時間去學習。就算有休息時間一般也是陪朋友打打農藥,吃吃雞之類的。

王哥 :嗯嗯,就這???

小林 :不然呢,不會吧不會吧,你平時工作也挺忙的樣子,居然下班還有時間去學習??

此時的小林內心不禁感到有些無奈,知識點錯綜亂雜,有些知識點掌握地似乎自我感覺良好,卻又總是能被面試官戳中盲區。

王哥 :這樣吧,我最近也在面試別人,我先來幫你大致做下模擬面試吧。

小林 :嗯嗯,好的,還是王哥你這兄弟靠譜。

於是王哥和小林兩人便開始了一場一對一的模擬面試場景....

王哥 :首先我們從一些網路基礎方面開始聊起吧,作為一名工作多年的java程式設計師,不應該只停留在crud層面,不知道你對於網路這塊的知識點了解得如何。下邊我將會從淺至深地詢問你一些關於網路的知識點。

小林正好前段時間準備了些網路的知識點,於是便開始表現得躍躍欲試了。

王哥的第一道問題便開始了:

你可以講解下自己對於三次握手的理解嗎?為啥要三次握手,以及三次握手中設涉及的細節點。

小林 :嗯呢,其實我對於三次握手的理解有過一定的整理歸納(前幾天剛剛看了某位大佬了這塊的文章(狗頭))。

為什麼要做三次握手?

個人的總結理解 這是為了保證通訊的雙方都具備有收資料和發資料的能力,而三次握手正好在最有限的次數中完成了這一項校驗工作。

三次握手中的細節點

首先連線端會發起一個SYN的訊號量,其中會攜帶幾個核心的引數,分別是ack,seq

這些標誌位引數在傳送的過程中會有一定的規律(seq和ack的規律有點記不太清楚了)。

如果三次握手成功,那麼就會繼續後續的網路通訊環節。

王哥: 嗯嗯,你說的大概意思我能理解,但是如果在面試過程中能說得更加詳細些就更好了:

首先三次握手應該分成三個階段,顯示SYN_SEND階段,這個階段中,客戶端會給服務端傳送一個SYN,接著在SYN-RECEVIED階段裡面,會返回ACK+SYN,最後在ESTABLISH環節客戶端會再次傳送ACK通知服務端客戶端具有接收資料的能力。

ps:關於三次握手的底層細節可以藉助一些抓包工具去實際操作進行理解。

小林: 嗯嗯,大佬所言極是。這些細節點我平時工作中都基本用不到,為啥你卻對它那麼熟悉呢?

王哥: 其實也沒有啦,這些東西偶爾在一些特殊場景還是會使用到的。不知道你有沒有用過一些特殊的抓包工具來對網路請求做過深入分析,如果有實踐過的話,這些問題應該難不倒你。

ps:通常在工作中我們都會使用fillder這款工具進行抓包,不過通常fiddler抓包對於一些tcp報文的解析並不友好,所以有時候可以嘗試使用下wireshark這款抓包工具。使用這款抓包工具有時候能對ACK,SYN這種包資訊有更深入對理解。

王哥:那麼你瞭解http2.0的一些新特性嗎?

小林:嗯嗯,在http2.0裡面出現了一個非常實用的特性,解決了傳統的序列化傳輸問題(例如字串的依次傳輸),採用並行傳輸的方式(在傳輸資料的時候,通過幀對資料進行順序標識傳輸的順序資料到達對方一端的時候重組資訊)。

王哥:嗯嗯。那下邊我們來聊聊你的一些專案細節點把。

小林:嗯嗯。

王哥:我看你的工作經驗主要還是以電商專案為主,你因該又遇到過秒殺型別的場景把,能講講自己在應對秒殺場景的時候的一些思路嗎?

小林:嗯嗯,我先自己整理下思路。

(內心瘋狂回憶以前的秒殺專案做法)

小林:嗯嗯,首先基本秒殺的邏輯是這樣的。使用者點選網頁,小程式,或者app等客戶端應用的下單按鈕,然後會進過一次查詢商品,生成訂單,鎖定指定商品,支付回撥,扣減庫存,更新訂單狀態,秒殺業務完成。

王哥:嗯嗯,問幾個問題哈。你在處理支付回撥的時候有遇到過哪些特殊情況嗎?

小林:嗯嗯,有的,有時候第三方的回撥會延遲,甚至是重複回撥,因此我們一般會在回撥介面那塊做冪等的防護機制處理。比較常見的方式是通過加入分散式鎖的技術方案來實現,在工作中一般也是藉助redis來實現分散式鎖,之前我也看了下專案內部分散式鎖的實現方式,是通過lua指令碼來實現的。

王哥:嗯嗯,你剛才提到來分散式鎖,那麼你對於一把合格的分散式鎖覺得需要考慮到哪些問題因素呢?另外為什麼不用zk來做分散式鎖呢?

小林:首先我來解答一下為什麼不用zk做分散式鎖。CAP理論告訴我們,一個分散式系統不可能同時滿足以下三種

  • 一致性(C:Consistency)
  • 可用性(A:Available)
  • 分割槽容錯性(P:Partition Tolerance)

這是因為zk本身更多是偏向於支援CP的模式,對於分散式鎖這類公用元件,通常使用場景都是需要對高可用有一定支援性,因此我們沒有使用zk來做分散式鎖。

需要考慮的問題場景:

  1. 當分散式鎖加鎖過程中,出現未知異常,需要主動釋放鎖,通常會採用try...finally的模版方式來做實現。
  2. 對於每次加鎖都應該設定超時機制,否則會一直處於搶佔資源的狀態不做釋放。尤其是高併發場景中,如果加鎖過程中出現了某些不可預料的情況,導致鎖沒有正常釋放,一直在redis中儲存且沒有設定過期時間,那麼會一直佔用redis的資源。
  3. 對於加鎖過程中,業務呼叫介面長時間堵塞(但是並沒有丟擲異常,例如說查詢資料的資料量非常大,處理時間很久),堵塞時間遠遠超過了加鎖的時常,那麼這個時候應該設計一種自動給鎖進行延期的機制。 ps: 這裡不妨可以參考一下redisson框架的設計思路,內部採用了watch dog機制來做這塊的優化。

王哥:嗯嗯,看來對於分散式鎖的一些應用你平時還是蠻有經驗的嘛。那麼我再問下你幾個問題把。在使用者點選秒殺搶單按鈕的時候,你會怎麼處理這塊的業務呢?

小林:嗯嗯,其實這個環節是屬於整個業務流程中併發量最大的部分來,對於這塊由於我之前的那個業務部門的秒殺併發數並不是很高,當時預計的tps在3000左右,針對這類業務場景而言,我當時給出了兩大點方案,首先是在客戶端做限流處理。也就是在點選按鈕的位置做攔截。

攔截方案有以下幾類:

  1. 點選按鈕一次之後,按鈕置灰,需要等待個三四秒之後才能再次請求,這一部分由前端的js來控制
  2. 對於一些惡意攻擊的黑客而言,可能會從js中看到按鈕請求的url,因此url也需要做攔截,我當時給出的方案是在url上邊加一個和使用者繫結關係的校驗引數(類似於token),每次請求的時候會在redis中儲存對應的key,value是指定的請求時間,下次請求的時候,如果後臺校驗發現該key的請求在最近的幾秒內有存在過訪問記錄那麼就不允許再次請求,減少對於程式下游的訪問次數。

這塊的限流指令碼是由當時的一些大佬編寫了一套lua指令碼放在了nginx上邊做限制。

王哥:嗯嗯,那為什麼要設計token來識別呢,用ip鑑別不是更加簡單嗎?

小林:雖然說使用請求的ip來鑑別一些惡意攻擊的請求是可以,但是ip做限流容易有“誤傷”的情況,例如說一些學校,醫院,公司這類場所,他們大多數的出口ip都是固定的,使用ip做識別防範的話,誤傷概率有點大。(經典面試題,敲黑板~~)

王哥繼續耐心聽小林分析下去。

小林:當時我們的服務在進行秒殺活動開啟之前對前端對一些靜態頁面做了預先載入的處理,頁面會被快取在了cdn上邊,當秒殺開啟之前,使用者無法進入到秒殺介面,當秒殺開啟的時候,會有後端一個定時指令碼去將cdn上邊的js做修改,客戶端載入到js之後,秒殺介面就會開啟。秒殺服務是一種典型的高併發場景,面對這種場景需要將後端的微服務進行單獨部署,以免拖垮其他機器,同時也方便擴容處理,另外對於頻寬也要特殊增加處理。

王哥:等等,你剛才說到了在cdn上加入一個js檔案來控制客戶端是否真正訪問到正式秒殺的頁面是嗎?能講下具體實現策略嗎?

小林:嗯嗯,是的。這塊當時是我們老大做的,細節點我也沒有太瞭解。

ps:關於如何控制頁面是否開啟實際秒殺頁面可以藉助使用JavaScript指令碼控制,在秒殺商品靜態頁面中加入一個JavaScript檔案引用,該JavaScript檔案中包含 秒殺開始標誌為否;當秒殺開始的時候生成一個新的JavaScript檔案(檔名保持不變,只是內容不一樣),並被使用者瀏覽器載入,控制秒殺商品頁面的展示。

如何防止瀏覽器,cdn,反向代理對這份檔案產生快取這個JavaScript檔案的載入可以加上隨機版本號(例如xx.js?v=32353823),這樣就不會被瀏覽器、CDN和反向代理伺服器快取。這個JavaScript檔案非常小,即使每次瀏覽器重新整理都訪問JavaScript檔案伺服器也不會對伺服器叢集和網路頻寬造成太大壓力。

王哥:好吧,那你後邊再去了解下,我們繼續吧。

小林:嗯嗯,當用戶下單成功之後,需要對請求進行限制,通常我們會將真實有用的請求先寫入一個訊息佇列中,避免請求都到達資料庫。後端會講商品的庫存載入在redis裡面,扣除庫存的工作在業務伺服器叢集中執行,先對redis中的庫存資料做校驗扣除,然後再更新到mysql中。當秒殺活動結束後,請求後臺的服務會返回一個秒殺活動結束的標識。大概就是這些吧。

王哥:嗯嗯,你大概把秒殺的一些簡單流程點給講明白了,但是其實在扣庫存,防止超賣,服務降級這些精華點卻似乎並沒有提及太多。

小林:那塊之前我並沒有負責,所以就沒有去做過多的瞭解......

王哥:哎呀,你這樣讓我問到 “高潮” 階段就突然沒了,感覺有點難受啊(狗頭),不過我看你前邊的基礎好像回答得也還可以,我們這邊正好最近也在招人,我幫你內推一下吧,你可以修改下簡歷發給我就好了。不過我只是一面的技術官,我這邊的老大對於技術要求非常苛刻,尤其是效能優化,分散式技術那方面,你可要好好準備下哦。

小林:好的,太讚了,好哥們兒,下班之後我請你吃頓宵夜。

未完待續....

原創不易,如果各位讀者喜歡,希望能點贊支援一下小林