阿里系統設計面試全流程:設計淘寶購物車系統的完整複盤

系統設計作者: 美歷團隊

4年Java後端經驗面試阿里系統設計,詳細講解設計淘寶購物車系統的完整過程,包括MySQL+Redis雙存儲、緩存策略、加購流程、高併發優化、大促場景處理

阿里系統設計面試全流程:設計淘寶購物車系統的完整複盤

背景介紹

我是2024年4月面的阿里,崗位是Java後端開發,4年經驗。說實話,阿里的系統設計面是我經歷過的最硬核的一場——面試官不只是讓你畫架構圖,而是會追問到數據庫表設計、分佈式事務、緩存一致性這些非常具體的層面。我面的這個組是淘寶交易核心團隊,所以面試官直接讓我設計淘寶的購物車系統。這個題目看起來簡單,但深挖下去涉及到的技術點非常多:高併發讀寫、數據一致性、分佈式鎖、緩存策略、消息隊列……我當時大概講了40分鐘,中間被追問了不下20次。下面是完整的複盤。

面試流程複盤

面試官是一位P8級別的技術專家,自我介紹說是淘寶交易架構組的。整個面試55分鐘,節奏非常緊湊,幾乎沒有喘息的時間。

前3分鐘:面試官簡單介紹了面試流程,然後直接出題:「請你設計一個類似淘寶購物車的系統。」我按照慣例先做需求澄清。

3-12分鐘:需求澄清階段。我問了以下關鍵問題:

1. 用戶規模?——「假設日活2億,大促期間QPS可達50萬。」

2. 購物車容量?——「單個用戶最多120個商品。」

3. 核心功能?——「加購、修改數量、刪除、選中/取消選中、合併購物車。」

4. 一致性要求?——「最終一致性即可,不要求強一致。」

5. 多端同步?——「需要支持PC、APP、小程序多端同步。」

面試官對我問的這些問題表示認可,說「需求理解得不錯,開始設計吧」。

12-40分鐘:這是最核心的環節,我按照存儲設計→緩存設計→核心流程→高併發優化→擴展方案的順序來講解。面試官在每個環節都追問了非常具體的問題,有些我回答得比較流暢,有些則被追問到詞窮。

40-50分鐘:面試官開始追問大促場景下的特殊處理,比如「雙11期間購物車QPS暴增100倍怎麼辦?」「購物車數據怎麼和庫存系統聯動?」「購物車價格怎麼實時更新?」

最後5分鐘:面試官讓我問問題,我問了團隊的技術挑戰和購物車系統的下一步演進方向。

真題詳解:設計淘寶購物車系統

一、存儲設計

購物車的存儲是整個系統的基礎,我設計了MySQL+Redis雙存儲方案:

1. MySQL主存儲:購物車表設計——user_id(用戶ID)、item_id(商品ID)、sku_id(SKU ID)、quantity(數量)、checked(是否選中)、create_time、update_time。核心索引:(user_id, item_id, sku_id)聯合唯一索引。

面試官追問「為什麼用MySQL而不是純Redis?」——我回答:1. Redis數據不能持久化保證不丟失,購物車數據是用戶資產,不能接受丟失;2. MySQL支持複雜查詢(如按店鋪分組),Redis需要多次查詢組裝;3. MySQL可以做數據分析和對賬。

面試官繼續追問「那為什麼不全用MySQL?」——因為MySQL的讀寫性能不足以支撐50萬QPS,需要Redis做緩存加速。

2. Redis緩存:用Hash結構存儲,key為cart:{user_id},field為item_id:sku_id,value為JSON(包含quantity、checked等)。這樣一次HGETALL就能獲取用戶整個購物車,比String結構逐個GET高效得多。

面試官追問「為什麼用Hash而不是String?」——String結構每個商品一個key,獲取整個購物車需要MGET,key數量多時性能差。Hash一次HGETALL搞定,且支持HINCRBY原子增減數量。

二、緩存策略設計

緩存策略是購物車系統最核心的設計之一,我講了讀寫策略和一致性保障

1. 寫策略:Write-Behind + 異步落庫。用戶加購時先寫Redis,然後異步寫MySQL。面試官追問「異步寫MySQL失敗了怎麼辦?」——我回答:1. 寫MySQL失敗會重試3次;2. 3次都失敗則寫入死信隊列,人工處理;3. Redis和MySQL之間有定時對賬任務,每5分鐘跑一次,發現不一致則修復。

面試官繼續追問「對賬期間用戶讀到不一致的數據怎麼辦?」——我承認這是一個trade-off,購物車場景可以接受短暫的不一致,因為購物車是輔助決策工具,不是交易系統。最終下單時會從庫存系統和價格系統實時獲取最新數據,購物車中的數據僅供參考。

2. 讀策略:Cache-Aside。讀購物車時先查Redis,命中則返回;未命中則查MySQL並回寫Redis,設置7天過期時間。

3. 緩存擊穿防護:熱點用戶的購物車用互斥鎖防止併發回源。面試官追問「互斥鎖怎麼實現?」——用Redis的SETNX,獲取鎖的線程查MySQL並回寫,其他線程等待後重試Redis。

三、核心流程設計

1. 加購流程

用戶點擊加購→網關鑑權→購物車服務→檢查商品有效性(調用商品服務)→檢查庫存(調用庫存服務)→寫入Redis(HSET)→發送MQ消息→異步寫入MySQL→返回成功。

面試官追問「檢查商品有效性和庫存會不會拖慢加購速度?」——確實會,所以我把這兩個檢查做成了異步預檢:加購時不檢查,直接寫入購物車,然後異步檢查。如果商品無效或庫存不足,標記該商品為「無效狀態」,用戶打開購物車時看到灰色提示。這樣加購接口的RT從200ms降到了20ms。

面試官追問「用戶加了無效商品會不會投訴?」——我們在購物車頁面會明確提示「該商品已下架」或「庫存不足」,用戶可以理解。而且大部分用戶加購後不會立即下單,等他們打開購物車時異步檢查已經完成,狀態是最新的。

2. 修改數量流程

用戶修改數量→購物車服務→Redis HINCRBY原子增減→發送MQ消息→異步更新MySQL。關鍵點:HINCRBY是原子操作,不需要加分佈式鎖。

面試官追問「如果用戶快速連續點擊+1,會不會出現數量不一致?」——不會,因為HINCRBY是原子操作,每次+1都會正確累加。但MQ消息可能亂序,所以MySQL更新時用quantity的絕對值而不是增量。

3. 合併購物車流程

用戶未登錄時購物車數據存在本地(Cookie/LocalStorage),登錄後需要合併到服務端。合併策略:本地購物車逐個與服務端比對,服務端已有的則數量取較大值,服務端沒有的則新增。

面試官追問「合併時併發衝突怎麼處理?」——用分佈式鎖(Redis SETNX)鎖定用戶的購物車,合併期間其他加購請求排隊等待。鎖的超時時間設為5秒,防止死鎖。

四、高併發優化

1. 熱點用戶分片:大促期間,某些頭部用戶的購物車訪問量極高(如主播帶貨場景)。解決方案:將這些用戶的購物車數據本地緩存一份,讀請求優先走本地緩存,寫請求同時更新本地緩存和Redis。

2. 批量操作優化:用戶全選/取消全選時,不要逐個更新Redis,而是用Pipeline批量執行,RT從N次網絡往返降到1次。

3. 限流降級:大促期間購物車QPS暴增,用令牌桶限流,超限請求返回「系統繁忙」。降級策略:關閉非核心功能(如購物車推薦、湊單提示),只保留核心的加購、查看、刪除功能。

4. 數據分片:MySQL按user_id分庫分表,每個庫8個表,共16個庫128個表。Redis Cluster按user_id的哈希值分配slot。

五、大促場景特殊處理

面試官特別追問了雙11場景下的處理:

1. 購物車與庫存聯動:用戶加購時只是「意向」,不鎖定庫存。下單時才真正扣減庫存。面試官追問「那購物車顯示的庫存是實時的嗎?」——不是,購物車顯示的庫存是準實時的,每5分鐘從庫存系統同步一次。如果用戶下單時庫存不足,會提示「庫存已售罄」。

2. 價格實時更新:購物車中的商品價格需要實時反映促銷活動。方案:購物車服務訂閱價格變更消息(通過MQ),收到後更新Redis中的價格。面試官追問「如果MQ消息延遲了怎麼辦?」——用戶打開購物車時,前端會調用價格服務獲取最新價格,作為兜底方案。

3. 購物車預熱:雙11前1小時,把活躍用戶的購物車數據從MySQL預加載到Redis,避免大促開始時大量緩存未命中導致MySQL被打崩。

六、擴展方案

1. 多端同步:用MQ廣播購物車變更事件,各端收到後刷新本地緩存。面試官追問「如果用戶同時在不同端修改購物車怎麼辦?」——以最後寫入為準(Last Write Wins),因為購物車場景下衝突概率極低,且衝突的影響有限。

2. 購物車推薦:基於購物車中的商品推薦關聯商品。方案:購物車服務調用推薦服務,推薦服務根據購物車商品的特徵向量做相似推薦。

3. 購物車分享:生成購物車快照,分享給好友。方案:購物車數據序列化為JSON,存入MongoDB,生成分享連結。

心得建議

1. 購物車系統的核心是緩存策略,面試官一定會追問Redis和MySQL的一致性問題。一定要想清楚寫策略(同步寫Redis+異步寫MySQL)和對賬方案。

2. 不要忽略大促場景,阿里面試官特別愛問「雙11怎麼辦」。提前準備預熱、限流、降級方案。

3. 存儲選型要說清楚理由,為什麼用MySQL+Redis雙存儲?為什麼用Hash不用String?每個選型都要有理有據。

4. 主動討論trade-off,比如「購物車數據允許短暫不一致,因為下單時會實時校驗」,這種表述非常加分。

5. 準備數據庫表設計,阿里面試官可能會讓你畫ER圖或寫建表SQL。購物車表的索引設計、分庫分表策略都要提前想好。

FAQ

Q:阿里的系統設計面和字節的有什麼區別?

A:阿里更偏工程落地,會追問到數據庫表設計、分佈式事務、緩存一致性這些非常具體的層面。字節更偏架構思路,關注你分析問題的框架和trade-off的討論。

Q:購物車系統的數據量有多大?

A:2億用戶,平均每人20個商品,總數據量約40億條。MySQL分庫分表後單表約3000萬條,在合理範圍內。

Q:沒有電商經驗怎麼辦?

A:購物車系統的設計思路是通用的:存儲選型→緩存策略→核心流程→高併發優化→擴展方案。你可以類比其他場景(如收藏夾、待辦事項)來講解。

#系統設計#阿里#购物车#Amazon#緩存策略#高並發#MySQL#Redis