iT邦幫忙

2025 iThome 鐵人賽

DAY 8
0

想像你正在為一家剛起步的精品咖啡店建立線上商城。老闆興奮地告訴你:「我們只有50種商品,每月大約1000筆訂單,預算有限但希望未來能擴展到全國。」這個看似簡單的需求,背後隱藏著電商系統設計的核心挑戰:如何在有限資源下建立一個既能快速上線,又保留未來擴展彈性的系統?

電商系統的複雜度常被低估。表面上只是「選商品、加購物車、結帳」三個步驟,但深入探究會發現每個環節都充滿技術決策:購物車資料該存在哪裡?如何處理並發下單導致的庫存超賣?支付失敗時如何確保資料一致性?

這些問題的答案,決定了系統能否從每天10筆訂單順利成長到每秒1000筆。今天,我們將從一個真實的角度出發,探討如何設計一個務實的電商系統。不追求過度工程,而是在適當的時機做出適當的架構決策。

場景定義與需求分析

業務場景描述

我們要設計的是一個B2C電商平台,初期服務單一品牌的線上銷售。這個系統不只是展示商品的櫥窗,更是連接品牌與消費者的數位橋樑。系統必須提供流暢的購物體驗,從商品瀏覽、選購到支付,每個環節都影響著轉換率。

因此,系統設計的核心價值在於確保交易的安全性與可靠性的同時,降低購物車放棄率,提升轉換率。

核心需求分析

功能性需求

  • 商品管理系統:支援多規格商品(如衣服的尺寸、顏色)、即時庫存顯示、商品分類與標籤管理、價格與促銷規則設定
  • 購物車功能:跨裝置同步(手機加入,電腦結帳)、訪客與會員購物車管理、購物車商品保存與過期機制、即時價格與庫存驗證
  • 訂單處理流程:訂單建立與狀態追蹤、庫存預留與釋放機制、支付整合與失敗處理、訂單確認與通知系統
  • 使用者系統:會員註冊與登入、訂單歷史查詢、收件地址管理、願望清單功能

非功能性需求

  • 效能要求:頁面載入時間 < 2.5秒(LCP標準)、API響應時間 < 200ms(P95)、支援同時1000個線上用戶、黑色星期五等促銷期間10倍流量承載能力
  • 可用性要求:99.9% uptime(每月停機時間 < 43分鐘)、零資料遺失的交易處理、自動故障轉移機制
  • 擴展性要求:從日訂單100筆到10,000筆的平滑擴展、支援未來微服務拆分、多語言多幣別擴展能力
  • 安全性要求:PCI DSS合規性、GDPR個資保護規範、防止OWASP Top 10安全威脅

核心架構決策

識別關鍵問題

技術挑戰 1:購物車狀態管理的複雜性
購物車看似簡單,實則涉及多重技術考量。當用戶在手機上瀏覽商品,加入購物車後改用電腦結帳,系統如何確保購物車內容同步?訪客轉換為會員時,如何合併購物車?這些場景直接影響用戶體驗與轉換率。

技術挑戰 2:庫存管理與並發控制
假設只剩最後一件限量商品,10個用戶同時點擊購買,系統如何確保不超賣?如何在保證資料一致性的同時,維持良好的用戶體驗?這個問題在促銷活動時尤其關鍵。

技術挑戰 3:支付整合與交易一致性
支付是電商系統最關鍵也最複雜的環節。當支付系統 timeout,我們無法確定交易是否成功時,該如何處理?如何確保「扣款」與「訂單成立」的原子性?

架構方案比較

單體架構 微服務架構 模組化單體
核心特點 所有功能在單一應用中 功能拆分為獨立服務 單一部署但內部模組化
優勢 開發簡單、部署容易、除錯方便、無網路延遲 獨立擴展、技術多樣性、故障隔離 保持簡單性、易於重構、未來可拆分
劣勢 擴展困難、技術綁定、部署風險高 複雜度高、網路開銷、資料一致性挑戰 需要良好的模組設計、仍有部署耦合
適用場景 小型團隊、快速驗證、預算有限 大型團隊、高流量、複雜業務 中型團隊、成長中的業務
複雜度

決策思考框架

diagram1

基於小團隊、預算有限、需要未來擴展性等條件,模組化單體架構是最佳選擇。

這個決策參考了Shopify的成功經驗:他們用模組化的Rails單體應用處理每分鐘2.84億次請求。關鍵在於從一開始就設計清晰的模組邊界,為未來的服務拆分預留空間。細節可參考下方業界案例

系統演進路徑

第一階段:MVP(0-1000 / 用戶)

架構重點:

  • 單一Node.js應用(Express.js框架) 或 Next.js 全端開發
  • PostgreSQL資料庫存儲所有資料
  • Redis處理session與購物車快取
  • 整合Stripe/綠界/TayPay等第三方服務作為支付系統
  • 部署在單一AWS EC2 或 Vercel

系統架構圖:

diagram2

為什麼這樣設計:

  • 簡單優先:單一應用降低運維複雜度,團隊可專注於業務邏輯
  • 成本考量:單機部署月成本約$100-200,符合預算限制
  • 快速迭代:整體部署允許快速修改和測試
  • 技術債務可控:清晰的模組劃分便於未來重構

這個階段的關鍵是建立穩固的資料模型基礎。例如以下核心資料表設計:

// 商品資料模型範例(示意用途)
interface Product {
  id: string
  name: string
  slug: string // URL友善的唯一識別
  basePrice: Decimal
  status: 'active' | 'inactive' | 'outOfStock'
}

interface ProductVariant {
  id: string
  productId: string
  sku: string // 庫存單位
  attributes: Record<string, any> // {size: 'L', color: 'red'}
  price: Decimal
  inventory: number
  reserved: number // 購物車預留數量
}

interface CartItem {
  userId?: string // 可為null(訪客)
  sessionId: string
  variantId: string
  quantity: number
  addedAt: Date
  expiresAt: Date // 購物車項目過期時間
}

第二階段:成長期(1,000-10,000 / 用戶)

架構演進重點:

  • 應用服務器橫向擴展(3-5個 instances)
  • 資料庫讀寫分離,增加讀取副本
  • CDN加速靜態資源與圖片
  • 引入訊息佇列處理非同步任務
  • 實施全面的監控與日誌系統

關鍵設計變更:

  1. 購物車優化策略

    • 原因:隨著用戶增長,購物車併發存取成為瓶頸
    • 實施方式:將購物車完全遷移至Redis,實施寫入合併策略
    • 預期效果:購物車操作延遲從200ms降至20ms
  2. 庫存管理改進

    • 原因:高峰期出現超賣問題
    • 實施方式:實施樂觀鎖定與庫存預留機制
    • 預期效果:完全避免超賣,庫存準確率達99.9%

diagram3

第三階段:規模化(10000+ / 用戶)

企業級架構特點:

這個階段開始考慮服務拆分,但採用漸進式的 Strangler Fig Pattern:

  1. 支付服務獨立:首先將支付邏輯抽離為獨立服務,降低PCI合規範圍
  2. 庫存服務分離:庫存管理獨立部署,支援更高的並發處理
  3. 通知服務外包:郵件、簡訊通知使用專門的服務處理

diagram4

技術選型深度分析

關鍵技術組件比較

技術選項 優勢 劣勢 適用場景
後端框架
Next.js 前後端同源,支持靜態生成與伺服器端渲染(SSR),開發效率高,內建API Route,簡化後端開發 大型複雜後端邏輯不適合,只適合輕量API,伺服器資源消耗較高 電商前台、行銷頁、具SEO需求的網頁、輕量API服務
Node.js + Express 統一前後端語言、豐富生態系、快速開發 CPU密集運算較弱 中小型電商、即時功能需求
Java Spring Boot 成熟穩定、企業級支援、強類型系統 學習曲線陡峭、開發速度較慢 大型企業、複雜業務邏輯
Python Django 快速開發、豐富套件、優秀ORM 效能較低、GIL限制 內容為主的電商、快速原型
資料庫選擇
PostgreSQL ACID合規、JSON支援、複雜查詢 水平擴展困難 交易資料、商品目錄
MongoDB 彈性schema、水平擴展、高效能 缺乏ACID、JOIN複雜 商品評論、用戶行為數據
快取方案
Redis 毫秒級延遲、豐富資料結構、持久化選項 記憶體成本高、單執行緒限制 Session、購物車、熱點數據
Memcached 極簡高效、多執行緒 功能單一、無持久化 純快取場景

技術演進策略

  • 初期技術(MVP階段):Node.js + PostgreSQL + Redis + React + TypeScript
  • 成長期調整:引入GraphQL優化API查詢、採用Next.js提升SEO
  • 成熟期優化:部分服務改用Go提升效能、引入Elasticsearch優化搜尋、考慮Service Mesh架構

實戰經驗與教訓

常見架構陷阱

  1. 過早優化陷阱

    • 錯誤:一開始就採用微服務架構
    • 正確:從模組化單體開始,逐步演進
    • 原因:不當的微服務拆分會導致90%的成本增加
  2. 購物車狀態管理錯誤

    • 錯誤:將購物車資料存在用戶瀏覽器
    • 正確:伺服器端狀態管理,客戶端只存ID
    • 原因:確保資料一致性,支援跨裝置同步
  3. 庫存超賣問題

    • 錯誤:檢查庫存和扣減庫存分兩步執行
    • 正確:使用資料庫層級的原子操作
    • 原因:併發情況下的競態條件會導致超賣

業界案例分析

Shopify的模組化單體成功

參考: Shopify Engineering - Deconstructing the Monolith

參考: ByteByteGo - Shopify Tech Stack

發展歷程

  1. 初期(2006-2010)

    • 架構特點:Ruby on Rails單體應用
    • 技術:單一資料庫、同步處理
    • 規模:數千商家
  2. 成長期(2010-2018)

    • 主要改進:引入Sidekiq處理背景任務、資料庫sharding
    • 遇到的挑戰:程式碼耦合嚴重、部署時間過長
    • 解決方案:開始模組化重構專案
  3. 近期狀態(2019-2025)

    • 當前架構特點:模組化單體(超過40個元件)
    • 規模:處理黑色星期五每分鐘2.84億請求
    • 未來方向:選擇性服務化,保持核心單體

關鍵學習點

  • 模組化優於微服務:對大多數團隊而言,良好的模組化設計比微服務更實用
  • 漸進式演進:不需要一次性重寫,可以逐步改進架構
  • 效能不是問題:正確的架構設計下,單體應用可以處理極高流量

監控與維護策略

關鍵指標體系

技術指標:

  • API響應時間 P50 < 100ms, P99 < 500ms
  • 資料庫查詢時間 P95 < 50ms
  • Redis命中率 > 95%
  • 錯誤率 < 0.1%

業務指標:

  • 購物車轉換率 > 30%(業界平均29.81%)
  • 頁面載入時間 < 2.5秒(影響SEO排名)
  • 支付成功率 > 98%
  • 庫存準確率 > 99.9%

維護最佳實踐

  1. 自動化策略:自動化測試覆蓋率>80%、資料庫遷移腳本版本控制
  2. 監控告警:設置Datadog或New Relic監控、PagerDuty實現智能告警升級、定期進行災難恢復演練
  3. 持續優化:每週效能審查會議、A/B測試新功能、定期安全掃描與更新

總結

核心要點回顧

  • 架構選擇重於技術選擇:模組化單體架構為多數電商專案提供最佳平衡點
  • 購物車是系統的心臟:正確的購物車狀態管理直接影響轉換率
  • 庫存管理需要悲觀設計:寧可顯示缺貨,也不要超賣
  • 支付整合要保守:選擇成熟的支付系統,不要自己處理敏感資料
  • 監控比功能更重要:沒有監控的系統等於盲飛

設計原則提煉

  1. 從簡單開始,保持演進能力:不要為未來可能不存在的問題過度設計
  2. 資料一致性優於效能:電商系統中,資料正確比速度快更重要
  3. 用戶體驗決定架構:技術決策應該服務於業務目標
  4. 成本意識貫穿始終:評估每個技術決策的TCO(總體擁有成本)
  5. 安全不是事後補充:從第一天就考慮PCI DSS合規性

進階延伸的關鍵字

針對今日探討的簡易電商系統設計,建議可從以下關鍵字或概念深化研究與實踐:

  • Event Sourcing與CQRS:透過事件溯源模式,可以完整記錄系統狀態變化,特別適合需要審計追蹤的電商場景。深入了解這個模式能幫助設計更靈活的訂單處理系統。

  • Saga Pattern:這是處理分散式交易的關鍵模式,學習如何在沒有分散式交易的情況下保證資料最終一致性,對於未來系統服務化極為重要。

  • Multi-tenant Architecture:探索如何設計支援多商家的電商平台架構,了解資料隔離、客製化、資源分配等挑戰的解決方案。

  • Headless Commerce:研究前後端分離的電商架構,了解如何通過API驅動的方式支援多管道銷售(網站、App、社交媒體、IoT設備等)。

  • Core Web Vitals優化:深入學習Google的網站體驗核心指標,掌握提升LCP、INP、CLS的具體技術,這直接影響SEO排名與轉換率。

可根據自身興趣,針對上述關鍵字搜尋最新技術文章、專業書籍或參加線上課程,逐步累積專業知識和實踐經驗。

下期預告

明天我們將進入第二週的學習旅程,探討「社交媒體動態牆系統」的設計。相比今天的電商系統著重於交易的準確性,社交系統更強調即時性與個人化。我們將深入探討動態排序演算法、內容推薦機制,以及如何處理每秒數萬則動態更新的技術挑戰。

從購物車到動態牆,看似完全不同的系統,背後卻有著相似的架構智慧:如何在有限資源下,為用戶提供最好的體驗。期待與你一起探索社交系統背後的技術奧秘!


參考資源


上一篇
圖片上傳分享系統 - 從檔案儲存到智慧分發的架構演進
系列文
30個系統設計實戰:全端工程師的架構修煉8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言