阿里二面:設計一個電商平臺積分兌換系統!

石杉的架構筆記發表於2019-05-24

轉自公眾號:狸貓技術窩

作者:原子彈大俠,高階技術專家

目錄

1.拉開差距的一類面試題

2.業務需求描述

3.對業務流程的思考

4.物流配送進度查詢,考慮到了嗎?

5.事務的保證

6.訊息中介軟體的引入

7.重試機制的引入

8.引入冪等性機制

9.對這類面試題的總結

1、拉開差距的一類面試題

現在面試經常會遇到一類問題,面試官讓你現場設計出某個業務場景下的一個系統,這個系統往往在業務或者技術上有一定難度,主要考察的是你多年積澱下來的系統設計的能力以及技術思維的能力。

類似的這類系統設計題目很多,比如:

  • 請你設計一個秒殺系統

  • 請你設計一個支撐百萬使用者的IM訊息系統

  • 請你設計一個微信紅包系統

  • 請你設計一個電商平臺積分兌換系統

這些題目本身都是開放式命題,沒有固定答案。遇到這種問題,一定不要慌,關鍵是在現場要思路清楚,有理有據,慢慢分析。

本文就其中一個問題:設計一個電商平臺的積分兌換系統,來詳細闡述一下。文中會詳細指出在系統設計的時候要考慮哪些要點,給大家展示出來這類問題思考的一個過程。

2、業務需求的描述

假設面試官現在給出來對於這個電商平臺的積分兌換系統的相關需求如下:

  1. 使用者在電商平臺裡平時通過購買商品、曬單評論可以有不斷的積累積分

  2. 積累到足夠的積分後,就可以在電商平臺的積分兌換頁面中,選擇使用自己的積分來兌換一些禮品

需求其實就這麼簡單,那麼面試官說了,針對這個業務場景給出你對這個機制實現的思考過程以及這裡要注意的一些地方。

3、對業務流程的思考

如何思考?首先,使用者不停的購買商品以及曬單評論,會不斷的獲取積分,那麼是不是需要一張積分表,專門用來儲存每個使用者的積分呢?

沒錯,這個表是一定需要的,可以現場給出下述的表結構。

積分表

  • id(自增id主鍵)

  • user_id(使用者id)

  • credit(積分)

繼續來看,假設在積分兌換頁面,使用者選擇用自己的20000積分兌換一瓶洗髮水,後臺的邏輯應該如何設計呢?

這個也是必須得現場給出一個思考過程的,這個其實看起來簡單,但是很多年紀較輕,經驗不足的朋友,可能沒法快速思考出來。

首先你要用20000積分去進行兌換,那麼一定是必須要在積分表裡扣減掉這20000積分的吧?所以在流程設計中,首先就得有一個20000積分扣減的過程。

其次,你用這20000積分兌換了什麼東西呢?

所以你是不是還需要一張單獨的表,叫做積分兌換記錄表,記錄下來你這個使用者本次用多少積分兌換了一件什麼商品?

這個積分兌換記錄表的結構如下所示,你是不是需要在下面的那個表裡插入一條記錄,說這個使用者本次用多少積分兌換了哪個商品?

積分兌換表

  • id(自增id主鍵)

  • user_id(使用者id)

  • exchanged_credit(用於兌換的積分)

  • product_id(兌換的商品id)

最後,光是插入上述那條積分兌換記錄是不夠的,你必須得呼叫倉儲業務模組的介面,通知倉儲業務模組新增一條發貨申請,而且應該是積分兌換對應的發貨申請,這樣保證倉庫可以準備對應的商品進行發貨。

這個發貨申請大致對應如下的表結構:

發貨申請表

  • id(自增id主鍵)

  • type(發貨型別,1:購買,2:積分兌換)

  • credit_exchange_id(積分兌換表的id)

  • product_id(要發貨的商品id)

其實這裡的發貨申請表簡化了很多,按理說還得有發貨商品的數量等等欄位,但是這裡可以簡化處理也沒事,畢竟是面試現場。

簡單畫出來這個流程大致如下所示。

阿里二面:設計一個電商平臺積分兌換系統!

4、物流配送進度查詢,考慮到了嗎?

如果把上面那整個業務流程給面試官說了,就完事了嗎?

當然不是!

你可以站在使用者的角度考慮一下,你是不是肯定還需要檢視積分兌換的記錄?這個在積分兌換表裡可以檢視到你用多少積分兌換了什麼商品。

但是你兌換商品的物流配送進度,能檢視到嗎?不能。所以你應該在業務流程裡再考慮進去對應的物流配送的邏輯。

通常來說一個基本的邏輯,就是在生產發貨申請單的時候,需要呼叫第三方物流公司的介面申請一個物流單,這樣倉庫管理員打包準備好商品,坐等物流公司商品收快遞就可以了。

物流公司會根據物流單去進行配送,這個配送地址當然是使用者自己在電商平臺選擇的自己的某個地址。

此時發貨申請單的表結構是不是如下所示?

發貨申請表

  • id(自增id主鍵)

  • type(發貨型別,1:購買,2:積分兌換)

  • credit_exchange_id(積分兌換表的id)

  • product_id(要發貨的商品id)

  • express_no(物流單號)

所以在生產發貨申請單時,先得呼叫第三方物流公司的介面申請一個物流單,這樣發貨申請單中是有一個物流單號的,而且每個積分兌換記錄都通過id跟發貨申請單關聯起來。

這樣在頁面上對每個兌換記錄,是不是可以找到發貨申請單中的物流單號,然後根據物流單號呼叫第三方物流公司的介面,去獲取配送的進度?

這就是一個非常典型的業務系統的技術實現的邏輯思考,一個經驗豐富合格的工程師,往往都具備了一定的業務思維,可以很好的根據業務系統中的使用者邏輯來考慮,反推自己的系統技術實現邏輯。

上述整個過程,如下圖所示:

阿里二面:設計一個電商平臺積分兌換系統!

5、事務的保證

業務流程整個捋順之後,接下來就涉及到技術的考慮了。你得考慮一下,這種業務系統裡怎麼能沒有事務呢?

扣減積分、新增積分兌換記錄、新增發貨申請單,這三個步驟必須是要麼一起完成,要麼一起失敗的。也就是說,這三個步驟必須是在一個事務裡的。

現在有一個問題,對一個電商平臺自身的業務系統來說,僅僅包含積分服務。但是倉儲服務一般是獨立部署的一套系統,或者是一個獨立的服務。

也就是說,扣減積分和新增積分兌換記錄可以在一個服務裡是一個事務,但是新增發貨申請單,他是在另外一個服務裡的,這個事務如何保證呢?

有朋友可能馬上回答:用分散式事務啊!先別急,我們們可以先用最簡單的模式來實現一下。

比如積分服務在一個事務程式碼塊中,先執行扣減積分、新增積分兌換記錄兩個步驟。

然後記住,在事務程式碼塊中,最後一步呼叫倉儲服務的介面,如果介面呼叫成功,那麼就可以提交事務了。如果介面呼叫失敗,那麼就拋異常讓事務回滾,這樣可以不可以?

這個流程如下所示:

積分服務 事務 {

-> 扣減積分

-> 新增積分兌換記錄

-> 呼叫倉儲服務

}

6、訊息中介軟體的引入

上述設計其實理論上是沒問題的,但是這裡你忽略了一個問題,在這個業務場景中,積分服務是沒有必要同步呼叫倉儲服務的。

因為積分兌換是一個使用者執行的操作,假設你的倉儲服務在生成發貨申請單的時候呼叫第三方物流公司的介面,被卡住了,或者失敗了,怎麼辦?

此時可能導致使用者在頁面上看到積分兌換按鈕點選之後,卡在那兒可能幾十秒都無法執行成功,所以這個系統如此設計是錯誤的。

那應該怎麼做呢?你必須得在這裡引入訊息中介軟體進行非同步化的解耦,保證使用者點選積分兌換按鈕之後,儘快返回。如下圖所示:


阿里二面:設計一個電商平臺積分兌換系統!

7、重試機制的引入

到這裡就OK了嗎?還沒呢!

一旦引入訊息中介軟體之後,好處是使用者點選積分兌換按鈕,直接就是在積分服務里扣減積分以及新增積分兌換記錄,然後傳送一條訊息到訊息中介軟體裡就結束了,速度很快,保證了使用者體驗。

但是壞處就是,萬一倉儲服務執行新增發貨申請失敗了怎麼辦?

這個時候就需要引入可靠訊息服務了,他需要去保證倉儲服務一定會完成新增發貨申請這個事。

具體的流程如下:

  • 積分服務傳送訊息給可靠訊息服務,可靠訊息服務在訊息表中新增記錄,然後傳送訊息到MQ(訊息中介軟體)

  • 然後倉儲服務消費訊息新增發貨申請單,如果成功就回撥可靠訊息服務的一個介面說自己成功了,可靠訊息服務就可以更新本地訊息表中的記錄狀態為成功

  • 如果倉儲服務長時間沒通知可靠訊息服務自己成功了,可靠訊息服務不停的重試再次傳送訊息

通過這樣的設計,就可以保證可靠訊息服務一定會無限次重試保證讓倉儲服務成功執行。再加上重試機制後,整個流程圖如下所示:

阿里二面:設計一個電商平臺積分兌換系統!


8、引入冪等性機制

最後一個問題,如果倉儲服務卡在第三方物流系統申請物流單的環節,長時間阻塞,所以沒回撥通知可靠訊息服務。

但是可靠訊息服務過了一段時間,感覺沒收到回撥通知,就自己重試傳送了訊息,這樣豈不是會讓倉儲服務新增兩條發貨申請單?

因此我們還要保證倉儲服務新增發貨申請單的冪等性,其實也非常簡單,回顧一下發貨申請單表的結構:

發貨申請表

  • id(自增id主鍵)

  • type(發貨型別,1:購買,2:積分兌換)

  • credit_exchange_id(積分兌換表的id)

  • product_id(要發貨的商品id)

  • express_no(物流單號)

只要在“credit_exchange_id”欄位上建立一個唯一索引就可以了,保證每個積分兌換記錄只能建立一條發貨申請單,如果重複建立就會被唯一索引被阻止,這樣就可以保證這個行為的冪等性了。

至此,對這道系統設計題目的回答,全部結束。

9、對這類面試題的總結

通過這篇文章的分析,可以看到對這類開放式面試題的一個回答思路,首先得從業務上來考慮這個系統應該有哪些業務組成部分,如何實現業務流程?

其次就是你得考慮面臨對應的業務場景的時候,這個系統會有哪些技術挑戰,各個環節可能會有哪些技術問題?

然後應該針對這些技術挑戰和技術問題,現場給出一些你的思路。只要給出大致的思路就可以,比如應該往哪個方向去解決,應該引入哪些機制。

說實話,大部分人是沒實際做過這類系統的。比如讓你設計一個秒殺系統,如何設計?

試問,國內有多少人真的做過秒殺系統?其實面試官只不過是通過這個問題考察你的技術面、技術功底,對各種常規技術方案的積累,以及現場分析業務,分析技術問題,進而基於你過去的技術積累,給出合理解決方案的一個能力。

這種能力,是一個高階Java工程師必須具備的能力,因為如果你是一個有5年以上經驗的高階工程師,那你必須在團隊裡能獨立負責一個系統。

此時你必須有這個能力,對專案面臨的問題,要能夠分析業務,分析技術問題,然後給出合理的技術方案和架構設計。

END


個人公眾號:石杉的架構筆記(ID:shishan100)

歡迎長按下圖關注公眾號:石杉的架構筆記!

公眾號後臺回覆資料,獲取作者獨家祕製學習資料

石杉的架構筆記,BAT架構經驗傾囊相授

阿里二面:設計一個電商平臺積分兌換系統!



相關文章