天天看點

面試官:深度不夠,建議回去深挖

作者:小傅哥

一、前言:為啥不要你?

​咱們這場面試完了,作為老鄉我想和你多聊幾句。​

從剛面試的問題回答中,能看得出你用了不少拙力背了不少題。直接拿這些技術點問,你可以回答。但同樣是這些技術點,我換個場景來問用到了什麼技術,你就像從沒有聽說過一樣。當然不可否認你能通過背把這些内容記住也是一種能力,但作為招聘從事軟體程式設計的碼農來說,其實更希望是招聘那些通過實際場景積累下來技術經驗研發人員,對各個技術點有張有弛,舉一反三。這也是一個理科生該具備的學習程式設計的基本素質,也更具有培養價值。

你肯定想,那為啥明明大部分時候都是CRUD開發,怎麼還那麼多要求呢?招進個人能幹活就行呗?

但其實能幹活的人多的是,你看;同類公司間為了市場有競争吧、公司内同部門為了業績有競争吧、部門内各小組為了績效有競争吧。那麼同樣一個事有的公司能做起來有的公司就不行,因為各個公司所具備的基因不同,而這個基因主要是來自公司選擇的市場面和相關人才積累。那麼放到各個公司部門内的小組也一樣,為啥有的組就那麼高績效、那麼多晉升名額、那麼多加薪包。那都是這個組内除了完成基礎項目一樣,還有很多具有超高素質的人才,所拼出來的。再拿這些拼出來的成績兌換成績效配置設定給組員。

現在縷清了,如果招聘一個組内平均能力以下隻能完成 CRUD 開發的,那麼就是招聘進來配置設定資源包的。放到組内沒有競争力、放到部門内墊底,是以上司根本沒有那麼多經曆培養一個社招的還需要大量時間培養的。—— 這樣的培養機會隻會給到應屆生。

是以在你度過程式設計階段的新手村階段以後,就不要把時間隻是放到背八股文,堆CRUD代碼上。這些東西搞多了,會讓人厭煩,吸收的不多,收獲的不大。而以大部分連八股文都能背的下來的人來說,把這樣的時間精力放到吸收有深度的技術項目上,同樣時間下成長的會更快。

這些東西本就沒有多難,難的是你不知道,從哪知道!—— 你不是學不會,你隻是沒有人帶你開開眼界!​

​你天天泡醬缸裡,你也能成鹹菜!​

二、深耕:科技與狠活!

但!有這樣的深耕技術的小傅哥在,我會幫你知道你不知道的,也會幫你知道你知道但沒法深知的。—— 這也是我的初心,成為粉絲最受信賴和尊重的技術号主。沉澱、分享、成長,讓自己和他人都能有所收獲!

接下來小傅哥就給大家舉一些場景案例,這也是當你缺少這些深度後,倒置你的履歷那麼空洞,你的回答那麼蒼白的主要原因。以下這些内容來自于粉絲讀者的提問後小傅哥給予的回答

1. 場景設計

問題:目前在做一個微商城系統,中間有一個類似購物車結賬,支援改價和使用優惠券等。目前遇到一個問題,就是優惠分為2種,一種是商品直減優惠,這種優惠我使用政策加責任鍊模式進行了重構優化能快速擴充。但是另一種是類似滿減優惠,需要根據各個商品在總價的比例均攤給不同的商品優惠金額,這裡我們使用的均攤算法是最後一個商品優惠金額等于總優惠金額-商品a-商品b的優惠金額,這樣能解決1/3這種小數問題。

回答:

  1. 背景(這類分攤計算的邏輯還是蠻複雜的,雖然複雜,但這類業務還是蠻有意思的)
  • 1.1 優惠類型可能包括:直減、滿減、N元購、折扣、優惠限定SKU
  • 1.2 支付方式優惠券,免息、分期百分比優惠、紅包
  • 1.3 合作分攤,包括優惠費用的承擔方,各自出資占比,有了出資後營運才能配置優惠券
  • 1.4 多種商品SKU組合購買 X 多種優惠組合支付 X 支付方式優惠(可選)
  • 1.5 部分商品退貨,根據優惠分攤金額扣除後,退款其餘部分。PS:但有時候也有業務需求是退款時候,分攤調整,所推商品金額如果能覆寫優惠券,則退回優惠券和剩餘金額。如:使用者支付了80元,買了5件商品,用了100-20的滿減優惠券,那麼1件商品退款的時候,退款了10元+20元滿減券。但也有時候是支援使用者選擇的,比如你同意退款15元還是退款10元+20元優惠券。具體要根據合規、風控、業務三方協調确定産品方案,有時候不同年度市場規則調整,可能也會随之處理分攤方式。
  1. 設計
  • 2.1 結構上使用模闆模式,因為分攤是一套标準的流程,具體分攤由不同的優惠券政策進行處理。
  • 2.2 在模闆模式中抽象類可以繼承資料支撐類和配置類,也可以結合政策模式、責任鍊模式等,便于組合使用。
  1. 流程
  • 3.1 接口中需要的核心參數包括:父單号、下單商品SKU清單、商品價格、實際支付、優惠券金額、優惠券資訊。當然可能這些資訊需要通過單号拆分後自己查詢組合,這個時候模闆模式的資料支撐類就發揮作用了。
  • 3.2 模闆模式的資料進行中,為商品清單提供分攤占比計算,A/(A+B+…N) 保持占比記錄。
  • 3.3 模闆模式分攤方法中for循環優惠清單,在循環方法中調用抽象分攤方法。
  • 3.4 在子類實作的抽象分攤方法中,調用優惠類型分攤計算政策方式。100-20 20元按照商品分攤比例,循環計算,并填充到抽象模闆中的Map<String, List<分攤對象>>中,key 是優惠ID。由于計算會有餘數,這部分分攤給最後一個商品。最終形成一組各個優惠分攤到每個商品SKU的分攤結果。
  1. 資料
  • 4.1 在資料庫中要記錄每一條的分攤記錄,商品父單、子單、金額、實付、優惠類型、占比、分攤金額等,這些友善後續進行退款以及結算給商戶使用。
  • 4.2 同時要有一張總表來記錄一個商品分攤後的完整資訊,是哪個商品父單、使用的優惠組合,這個表有點和訂單表類似,不過會填充一些分攤資訊與4.1表1vn的結構。
  1. 擴充
  • 5.1 新提供的分攤優惠券了類型政策,采用資料庫配置的方式處理,并在程式啟動的時候,加載到分攤模闆的Config中,這樣就可以處理新增的分攤計算方式了。
  • 5.2 不過可能有時候實際的業務訂單要比分攤系統快,那麼這個時候出現的訂單,不能分攤則要做歸檔處理,寫入歸檔表,後續開發了新的分攤政策和配置,再開啟任務掃描處理分攤。

2. 技術問題

技術問題的解決能力,需要來自于程式設計上的日積月累,參與更多的場景,碰到更多的問題。這樣才能積累經驗,為此小傅哥專門收集實際開發中所遇到的異常并進行模拟複現。讓大家更好的吸收這些實戰經驗。

面試官:深度不夠,建議回去深挖

2.1 rollback-only

  • 問題:rollback-only
  • 異常:線程執行某個定時任務,在事務送出時抛出了異常。看到rollback-only字樣,這個是什麼原因引起的。寫代碼要注意什麼能避免産生這一種情況。
  • 測試:用資料庫表防重做插入測試,觸發異常;
  1. 兩個方法都加了事務注解,兩個方法都會受到到事務管理的攔截器增強,并且事務傳播的方式都是 REQUIRED,當已經存在事務的時候就加入事務,沒有就建立事務。這裡A和B都受事務控制,并且是處于同一個事務的。
  2. A調用B,A中抓了B的異常,當B發生異常的時候,B的操作應該復原,但是A吃了異常,A方法中沒有産生異常,是以A的操作又應該送出,二者是互相沖突的。
  3. Spring的事務關聯攔截器在抓到B的異常後就會标記rollback-only為true,當A執行完準備送出後,發現rollback-only為true,也會復原,并抛出異常告訴調用者。
  • 複現:​​https://gitcode.net/KnowledgePlanet/CodeTutorial/Bug-Code/-/blob/master/src/test/java/cn/bugstack/guide/test/RollbackOnlyTest.java​​

2.2 Deadlock

  • 問題:死鎖
  • 異常:Deadlock found when trying to get lock; try restarting transaction
  • 測試:多線程模拟并發下,一個事務未送出完成,又來一個事務。
  • 複現:​​https://gitcode.net/KnowledgePlanet/CodeTutorial/Bug-Code/-/blob/master/src/test/java/cn/bugstack/guide/test/DeadlockTest.java​​

2.3 主從同步

問題:在高可用場景中,資料庫會做主備,那麼當主資料還沒來的急同步到備資料庫,主資料庫挂掉了。這種場景如果是對資料一緻性要求比較高的情況下,架構又該如果考慮,業務又該如何補償呢。

  • binlog 說明;用于記錄資料庫執行的寫入性操作,以二進制儲存在磁盤。binlog 是 mysql 的邏輯日志,由 Server 層進行記錄,使用任何存儲引擎的 mysql 資料庫都會記錄 binlog 日志。實際應用中,binlog 用于主從複制、資料備份。
  • binlog 分類;STATMENT、ROW、MIXED,mysql 5.7.7 之前預設格式為 STATMENT,5.7.7 之後預設為 ROW;可以通過指令檢視 mysqlbinglog mysql-bin.00001 | more
  • 1 STATMENT:基于 SQL 語句複制,每一條修改SQL語句都會記錄到binlog
  • 2 ROW:基于行複制
  • 3 MIXED:基于 STATMENT、ROW 的混合模式
  • 主從複制:Mysql 主從複制需要三個線程:master(binlog dump thread)、slave(I/O thread 、SQL thread)
  • 1 binlog dump線程: 主庫中有資料更新時,根據設定的binlog格式,将更新的事件類型寫入到主庫的binlog檔案中,并建立log dump線程通知slave有資料更新。當I/O線程請求日志内容時,将此時的binlog名稱和目前更新的位置同時傳給slave的I/O線程。
  • 2 I/O線程: 該線程會連接配接到master,向log dump線程請求一份指定binlog檔案位置的副本,并将請求回來的binlog存到本地的relay log中。
  • 3 SQL線程: 該線程檢測到relay log有更新後,會讀取并在本地做redo操作,将發生在主庫的事件在本地重新執行一遍,來保證主從資料同步。
  • 複制過程:
  • 1 主庫寫入資料并且生成binlog檔案。該過程中MySQL将事務串行的寫入二進制日志,即使事務中的語句都是交叉執行的。
  • 2 在事件寫入二進制日志完成後,master通知存儲引擎送出事務。
  • 3 從庫伺服器上的IO線程連接配接Master伺服器,請求從執行binlog日志檔案中的指定位置開始讀取binlog至從庫。
  • 4 主庫接收到從庫的IO線程請求後,其上複制的IO線程會根據Slave的請求資訊分批讀取binlog檔案然後傳回給從庫的IO線程。
  • 5 Slave伺服器的IO線程擷取到Master伺服器上IO線程發送的日志内容、日志檔案及位置點後,會将binlog日志内容依次寫到Slave端自身的Relay Log(即中繼日志)檔案的最末端,并将新的binlog檔案名和位置記錄到master-info檔案中,以便下一次讀取master端新binlog日志時能告訴Master伺服器從新binlog日志的指定檔案及位置開始讀取新的binlog日志内容。
  • 6 從庫伺服器的SQL線程會實時監測到本地Relay Log中新增了日志内容,然後把RelayLog中的日志翻譯成SQL并且按照順序執行SQL來更新從庫的資料。
  • 7 從庫在relay-log.info中記錄目前應用中繼日志的檔案名和位置點以便下一次資料複制。
  • 降低延遲:
  • 從庫上的執行,即sql_thread更新邏輯,在5.6版本之前,是隻支援單線程,那麼在主庫并發高、TPS高時,就會出現較大的主從延遲。是以,MySQL自5.7版本後就已經支援并行複制了。可以在從服務上設定 slave_parallel_workers為一個大于0的數,然後把slave_parallel_type參數設定為LOGICAL_CLOCK
  • 降低多線程大事務并發的機率,優化業務流程
  • 優化SQL,避免慢查詢,減少批量操作
  • 提高從庫機器配置
  • 主從同機房、通網絡、帶寬、地域
  • 主從切換,日志恢複

3. 技術架構

面試官:深度不夠,建議回去深挖

總有同學分不清 MVC 和 DDD 的本質差別,卻又總被一些理論搞的暈頭轉向,聽不懂:領域專家、戰術戰略、模型推演等,這些詞讓原本就模糊的概念更加模糊,根本沒法落地。是以給大家畫了一個 MVC 和 DDD 的對比圖,便于大家可以從代碼實作視角的更好的了解DDD。

MVC:更偏向與資料模組化實作,由資料調用驅動,是以也就引申出的DAO、PO、VO類會随着項目開發不斷的膨脹,不易于疊代和維護。

DDD:以業務流程提煉領域模型為驅動,設計和實作子產品開發,在一個領域中包含mode對象、倉儲資料、服務實作,也更注重設計模式的使用,否則實作的DDD徒有其表更多的隻是歸類了 DAO、PO、VO 對象。

是以如果想了解DDD如何落地,非常建議把DDD抽獎系統的代碼好好實踐起來。

4. 學習運用

問題:手撸spring、手撸MyBatis如何展現在履歷上?小傅哥可以給個Demo嗎

  1. 展現在專業技能上,例如;

    1.1 深入學習 Spring 核心流程子產品,包括;IOC、AOP、依賴倒置等流程,掌握Spring解決複雜場景所運用的分治、抽象和知識(設計模式、設計原則),在解決Spring場景問題時,可以從核心原理上給出方案。同時也具備基于 Spring 開發 SpringBoot Starter 技能,為複雜項目減少同類共性需求的開發,凝練通用的技術元件,減少研發成本。

    1.2 深入學習 MyBaits 核心流程子產品,包括;會話、反射、代理、事務、插件等流程,熟練掌握 ORM 架構的設計思想、實作方式和應用價值。并能按需結合 MyBatis 的插件機制,開發屬于企業自己所需的功能,包括;資料分頁、資料庫表路由、監控日志、資料安全等方面。

  2. 展現在項目經驗上,例如;—— 對校招和實習比較有用

    把 Spring、MyBatis 當一個學習項目來描述,這是你在離校前,最可能接觸到的一個完整的、成型的、知名的,有企業使用的,架構。你就按照自己學習并開發了這樣一個架構為目标來寫項目,并描述出這個項目,你用了什麼技術棧,解決了什麼問題,學習到了哪些。

  3. 展現在項目應用上,例如;

    關于 Spring、MyBatis 的項目,一般都是插件類開發,比如各類的 SpringBoot Starter,MyBatis 插件,都是基于架構的深入整合類技術解決方案,展現在履歷上,非常抓眼球。一看你就是有深度和自研能力的研發人員。—— 一般不讓你造輪子,但需要你有造輪子的能力,這樣企業中一些軟體可以被你進行優化和修改。

  4. 展現在解決問題是上,例如;

    在你的自己的業務項目中,滲入一些關于解決了原項目使用 Spring 時,關于感覺 Aware 方式或者結合 FactoryBean 包裝對象等,所遇到的問題,因為你學習過源碼,是以非常清晰這樣的流程,是以解決了一個問題。通用 MyBatis 也适用于這樣的描述方式,包括;事務、查詢次數、批查詢、插件能監聽到的四個類(ParameterHandler、ResultSetHandler、StatementHandler、Executor )你給了更好的選擇。

5. 更多場景