这段视频深入剖析了支撑大型电商平台(如亚马逊)在“黑色星期五”等极端流量下的系统架构。核心思想是**分离原则**,即将一个看似统一的电商网站拆解为多个独立的子系统,每个子系统针对其核心任务进行优化。
首先,针对**商品搜索**,系统不会直接查询庞大的主数据库,而是使用ElasticSearch构建倒排索引,并利用Redis缓存热门搜索结果,实现毫秒级响应。其次,面对**购物车**的高并发写入挑战,系统放弃了传统的数据库锁,采用多主复制架构和CRDT(无冲突复制数据类型)数据结构。CRDT不存储购物车的最终状态,而是存储一系列带唯一ID的操作记录,从而在数学上保证来自不同设备的并发操作不会互相覆盖,即使有毫秒级的同步延迟。
最关键的**库存管理**环节,系统采用了反直觉的设计:将接收订单与扣减库存完全解耦。通过Kafka和Flink构建事件驱动流,当用户下单时,系统立即接受订单并丢入消息队列,而非立即查询库存。所有针对同一商品的订单会被路由到同一个Flink处理单元,该单元在本地内存中进行原子级的库存递减,避免了数据库锁带来的性能瓶颈。这种设计接受了“先卖后道歉”(即超卖后退款)的商业策略,换取了系统在流量洪峰下的超高可用性。
此外,系统还通过CDC(变更数据捕获)触发降价通知,并使用SSE(服务器发送事件)进行高效的大规模广播。在容错方面,采用双重写入策略,确保缓存崩溃时数据不丢失,系统仅降级运行。整个架构的哲学在于:永远不依赖单一数据源,通过分离、异步、事件驱动和数学保证(如CRDT),将复杂的分布式问题转化为可控的本地问题。
Transcription
786 Words, 9534 Characters
Chinese 哈囉大家好 歡迎回到AI範圍報
你有有沒有想過當你每天打開SPA的法律廳歌
或是在Uber上叫車時
背後那個能支撐全球千萬人同時使用的大腦到底是長什麼樣子的
今天這個單元是 系統設計藍藍學
希望透過20分鐘用輕鬆的方式
我們一起深度採解這些頂級的大型軟體架構
畢竟在AI時代懂得怎麼把這塊拼圖拼好
比會寫扣的還要重要的多
那我們就開始吧
今天我們要採解的是電商平台的系統架構
而且我們要把它拉到最極端的狀況來看
像是黑色星器物購物節
有超多限量商品全球都在同一秒鐘搶購
這個系統最核心的挑戰
數白了就是一個很矛盾的需求
你同時需要搜尋你型的閃電班的速度
又要向銀行轉帳那樣超級精確
而且要在3秒內完成還要程度全球好幾個試用症
光聽就覺得頭皮發麻了吧
今天這集我參考了幾位在業界很有影響力的工程師的觀點
主要來自YouTube上像是Alexude的System Design Interrupt頻道
還有郭老師的技術分享
以及一些在Amazon和FoodCut做過後端服務的工程師分享的實戰經驗
他們把這套架構拆解的很細
我今天幫大家整理成一個可以聽懂
也能帶經驗室的版本
在我們進入技術細節之前
我想先拋幾個問題讓你帶著好奇心聽下去
第一,當你搜尋PS5的時候
系統怎麼在E1比商品裡面
幾乎瞬間就找到你要的東西
第二,你跟家人共用一個掌號
兩個人同時在不同裝置加東西到狗屋車
為什麼東西不會互相蓋掉
第三,也是我覺得最精彩的
當1萬個人同時搶通一個限量商品
系統怎麼在不當季的情況下
處理這個瞬間爆炸的流量
這三個問題的答案背後都場著非常聰明的設計決策
好,那我們一個拆解
首先,我們先來建立一個規模感
我們這個系統設計的目標是11個註冊使用者
正常的一天大概會處理E1比訂單
E1比訂單聽起來很多
但平均下來大概是每秒鐘處理1100多比訂單
商品目錄有11個品項
如果每個商品的基本資料、描述
屬性加起來只要E&B
整個商品目錄就是一個PB
也就是1000個TB的資料量
也沒辦法把這麼有龐大的資料塞進一台電腦
然後就資料庫去搜尋它
使用者對這個系統有3個期待
而這3個期待根本是互相衝突的
第一,它們要搜尋一個PB的資料
而且要快到像是瞬間完成
第二,它們要跟家人共用賬號
從不同裝置同時操作購物車
而且資料不能消失
第三,它們要確定自己按下利己購買的時候
那個謹慎一件真的是留給它們的
要同時做到這三件事
就是這個系統最根本的難題
如果你從民開始用一個小團隊來建立這個系統
你最指振的做法就是一個大型單體架構
開一台伺服器,接一個大型的觀點是資料庫
比方說PASSQUARE SPUEL,然後把使用者
商品購物車訂單都塞進去
使用者搜尋就下查詢
加購物車就更新那一列資料
結帳就把庫存數量建議
這個做法在小規模完全沒問題
但一旦放大到這個等級
有兩件事會讓它直接爆掉
第一,搜尋一個PB的問制資料
用一般的資料庫查詢
就像你要在一座圖書管理找一句話
但你的方法是從第一本書的DNA開始讀
一本一本讀下去
這不是幾毫秒,這是幾分鐘的事
第二當幾百萬個人同時在購物
觀點是資料庫會一直在鎖定跟接鎖資料列
整個系統的處理速度就會慢到幾乎停擺
真正在業界跑的架構
核心思路只有一個字、差異
電商平台不是一個應用程式
它是好幾個完全不同的系統
只是偽裝成同一個網站
商品摸錄是一個獨居為主的系統
需要特化的搜尋引擎跟快取程
購物車是一個高度病發的分散式儲存系統
它寧可犧牲一點積時準確信
也要保持高可用心
節障流程是一條嚴格控制的非同步處理管線
把庫存問題當成工廠的生產現來處理
他們不用一個資料庫
他們又好幾個
每一個都針對特定功能做最佳化
好,這樣我們就把大型架構的輪廓建立起來了
接下來我們要一個生娃
第一個生前主題商品搜尋
問題是你有十億個商品
怎麼在幾毫秒內找到使用者要的東西
最直覺的做法是
直接用主要資料庫來搜尋
假設你選了MangoDB
一種Noise QL的資料庫
因為商品屬性差異很大
一見TX有尺寸跟顏色
一台筆電有記憶體跟處理器
MangoDB讓你很彈性的儲存這種不規則的資料
所以你見了一個搜尋功能
使用者輸入床電
系統就取MangoDB裡面找所有標題
或秒數裡面有床電這個資料
在商品只有1000筆的時候
這完全沒問題
半秒鐘就回來了,很合理
但當你有十億筆資料
這個方法就會整個垮掉
要在一個PB的資料裡面做文字筆對
資料庫要把大量的資料從硬碟搬到記憶體
處理器直接標到100%
記憶體一出一個差勋可能要跑好幾分鐘
更糟的是,當資料庫在吃力的處理這個搜尋的時候
外加新增商品的請求也會一起卡住
整個商品墓入直接停擺
真正的解法是把搜尋功能
完全從主要資料庫裡面切出去
用一個叫做倒排說音的東西來處理
你可以把倒排說音想像成教科書後面的說音頁
你不需要從頭讀整本書才能找到
滑聖頓這個名字出現在哪裡
你直接翻到最後查滑聖頓
他直接告訴你第幾頁
這就是倒排說音的概念
不是從資料去找關鍵字
而是從關鍵字直接對應到有哪些商品
要做到這個規模
公司會用一個專門的搜尋引擎
叫做Elastic Search
這是一種專門位全文搜尋設計的引擎
特別擅長處理這種大規模文字查詢
那問題來了
當賣家在MangoDB新增一個商品
Elastic Search怎麼知道要跟心他的說音
這裡用的是一個叫做CDC的技術
全面是千劑Data Capture
也就是資料一動捕捉
CDC就像一個堅實器
一直盯著主要資料庫
只要有任何資料擺動
他就馬上把這個事件推進一個訊息註練
你可以把訊息註練想成一個數位版的排隊等待區
資料在這裡等著被處理
Elastic Search從這個註練裡面讀資料
在背景更新他的說音
主要資料庫完全不需要碰受尋這件事
但到了Amazon這個等級
就算是Elastic Search會遇到平靜
因為你有11個商品
你沒辦法把整個說音放在一台機器上
你必須把它切開
分散到幾百台似乎7
這裡有兩種切法各有各的問題
第一種叫做關鍵字切分
也就是把同一個關鍵字對應的所有商品
全部放在同一台似乎7上
理想狀況下
使用者搜尋床電
你只需要問那一台似乎器
超快
那問題是鞋子或書這種超級廣的關鍵字
對應的商品數量龐大到根本塞不經濟台機器的音碟
所以實際上他們用第二種
文件切分
也就是把商品隨機分散到幾百台似乎7上
當使用者搜尋鞋子
系統必須同時問所有似乎器
你那邊有鞋子嗎
然後等所有似乎器回答把結果整合起來
按小關鍵排序再回傳給使用者
這個疑問多達在整合的過程
計算成本很高
延遲也會上升
那怎麼把延遲壓到100毫米有一下
他們用了一個很直接的方法
快去
也就是把常用的資料暫時存在記憶體力
下次要用就不用再重新算
他們知道每天有幾百萬人在搜尋PS5或Nighty球鞋
所以他們在每天晚上跑一個大型的PS處理工作
把最熱門的搜尋詞預先算好
第一頁的結果
然後把這些結果存進Redis
一種把資料存在記憶體力的快取系統
速度非常快
當你搜尋熱門商品
系統先去Redis查
直接在記憶體找到已經算好的結果
幾毫秒就會傳點你
也在Stix Search的基群
完全不需要處理這大多數的流量
所以這邊的重點就是在這個規模下
你沒辦法用同一個資料庫同時搞定
儲存商品跟搜尋文字這兩件事
你必須把他們拆開
然後用快取來掩蓋分散式搜尋的延遲
好哦讀取的問題算是解決了
但搜到商品只是第一步
接下來使用者要把東西加進購物車
這裡藏了一個很多工程師
第一次看到都會採個坑
第二個申錢主題購物車的頻發問題
問題是當多個人或同一個賬號的多個裝置
同時在操作同一個購物車
怎麼確保資料不會互相蓋掉
最直覺的做法是用標準的資料庫更新操作
假設媽媽跟兒子共用一個Amazon帳號
媽媽在公司用筆電
兒子在學校用手機
購物車目前是空的
媽媽點了一本書加入購物車
她的流氧器
賭到空的購物車加入書
然後送出指令給伺服器
叫她把購物車更新成一本書
就在同一毫秒
兒子點了一個電玩遊戲
加入購物車
和手機也賭到空的購物車加入遊戲
然後送出指令叫伺服器把購物車更新成一個遊戲
兩個請求幾乎同時到達
直到酷
晚一圍秒到的那個
會直接把錢一個覆蓋掉
這個現象叫做
直到覆蓋
就是直到互相蓋掉
媽媽去結帳的時候
數不見了
只剩遊戲
這看起來像是一個很邊緣的狀況
但在11個使用者的規模下
只要有1%的機率發生
並發購物
每天就有1000萬的人的購物車
在互相蓋掉對方的資料
這是每天幾百萬美元的損失
只因為東西從購物車裡消失了
你可能會想那用WIP SAUKETER
WIP SAUKET是一種讓手機和伺服器
保持即使連線的技術
如果媽媽加了一本書
伺服器可以馬上把這個更新
推薄到兒子的手機
但這個方法在大規模下也行不同
第一幫幾千萬的使用者維持
開著的WIP SAUKET連線
光是這件事就會吃掉大量的伺服器記憶體
第二
它根本沒有解決競爭條件的問題
如果兩個人真的在同一毫秒按下按鈕
WIP SAUKETER訊息根本來不及在網路上
跑一趟再回來
覆蓋問題還是會發生
如果規模真的大到這個程度
很多團隊會乾脆換一個想法
不要每次都改同一份購物車資料
真正的解法是
完全放棄標準的資料庫更新
電商巨頭用的是一種
特殊的NoSQL資料庫
像是ReaK或CutSanDro
這類資料庫被設定成多組接電複製的模式
意思是不只有一個主要資料庫
而是在全球各地都有多個主階點
媽媽的邪路請求去紐約的四服器
而是的邪路請求去加州的四服器
這種多組接電複製
意思是說你的資料庫不只一個
而是很多個
每個都是老大
可以獨立處理邪路
這樣可以大大增加處理速度
還容錯能力
一可能會問
這樣不是讓覆蓋問題更嚴重嗎
紐約跟加州怎麼達成共識
購物車裡面到底有什麼
他們用了一個很精彩的電腦科學概念
叫做CRDT
中文可以翻成無衝突複製資料型別
簡單說就是一種數學上保證
不會產生衝突的資料結構
關鍵在於它不儲存
購物車的最終狀態
而是儲存一連串的操作記錄
具體來說
他們用的是一種叫做
Observe Remove Set的結構
運作方式是這樣的
當媽媽加入的本書
紐約的四服器不是存一個清單
而是產生一個唯一的隨即ID
我們叫它標籤
然後存下一個事件
標籤
加入書
而自在加州加入遊戲
加州的四服器存下
標籤比加入遊戲
在背景紐約跟加州的四服器
會持續互相同步資料
當他們合併的時候
不會覆蓋任何東西
而是把兩邊的事件集合
直接合併
因為標籤
A跟標籤B是唯一的
資料庫可以完美地把他們合在一起
購物車裡就同時有書跟遊戲了
沒有任何資料對我實
如果媽媽後來三張的本書
系統就寫入一個新事件
標籤A移除
當兩邊同步的時候
系統看到標籤
A有一個加入跟一個移除
兩個互相抵銷
書就消失了
這個設計精采的地方在於
它完全不需要資料庫鎖定
系統可以每秒接受幾百萬個
購物車更新
完全沒有平景
當然這裡有一個取捨
就是最終一隻新
因為兩邊的資料庫
是在背景同步的
可能會有50到100毫秒的時間差
媽媽暫時看不到
兒子剛加入的遊戲
系統用這一點點的即時性換來個保證
任何人的操作
永遠不會因為病發而被意外閃掉
所以說白了
當你有大量的病發協助
用標籤的資料庫更新
只會把你的資料搞壞
改成儲存操作記錄
而不是最終狀態
你就可以用數學來保證
每個使用者操作都被保留
即使跨越全球的網路也一樣
另外這裡也要理清一下
前面提到的Radeys主要是用來快取
熱門搜尋結果
購物車的權威資料
也就是那個永遠不會錯
最終狀態的資料
還是會儲存在像
Casandra這種石球化資料庫裡
我知道剛剛連續講的兩個
很密集的技術概念
我們暫停一下整理一下
到目前為止
我們有了一個超快的搜尋程
還有一個不會讓資料互相覆蓋的購物車
接下來是最關鍵的一步
使用者按下確認訂購
這裡的規則完全不一樣了
第三個生前主題
庫存管理與先賣在道歉的設計哲學
問題是
1萬個人同時要買同一個先量商品
系統怎麼處理
最直覺的做法叫做悲觀鎖定
一個出界工程師看到這個問題
第一反應是
這是金融交易
我要確保嚴格的ACID特性
CID是一組資料庫的保證
確保每比交易都被可靠地處理
所以他用一個關聯式資料庫
當使用者按下購買PS5
資料庫就在PS5的庫存來列
加上一個所
讀取現在的數量檢移
存回去
然後解鎖讓下一個人進來
這個邏輯完全合理
他用數學保證庫存絕對不會掉到0以下
但我們來看一下數字
1萬個人同時接賬
第一個人拿到所
其他9999個人在排隊等
一個標準的資料庫大概每秒
可以處理擊敗各這樣的鎖定操作
也就是說排在後面的人
可能要等10秒20秒甚至30秒
在網路的世界裡
一個請求超過10秒沒有回應
似乎其實就會拋出預使錯誤
使用者的流然器當掉
他們重新整理業面
又送出一個新的請求給資料庫
讓助列變得更長
這是一個雪崩式的失敗
整個結賬服務直接融斷
你沒辦法用資料庫鎖定
來處理高速的庫存扣件
那真正的解罰是什麼
這裡很煩之絕
因為我們第一個念頭通常是
那就說起來
但電商巨頭的處理方式
是把接收訂單
跟扣檢庫存這兩件事完全拆開
用一套事件驅動的串流架構來處理
核心工具是
Patch Cuff Car
跟奧牌學Fling
Cuff Car是一個分散式的訊息代理系統
你可以把它想成一條超高速
幾乎不會壞的輸送帶
資料在上面排隊等著被處理
Fing是一個串流處理系統
它從內條輸送帶上獨資料
然後即使對資料做計算
實際的架構是這樣運作的
當你按下確認訂購
伺服器完全不去查庫存資料庫
一點都不查
它只是接受你的訂單
驗證你的付款資訊
把訂單丟上Cuff Car的輸送帶
然後馬上告訴你的流氧器訂單成立
等等它沒有查庫存
對就是這樣
這是一個有商業決策驅動的技術選擇
公司決定高可用性
也就是節障
絕對不能當機
比嚴格的庫存一支新更重要
他們接受先賣在道線這個模式
接受一萬筆訂單
然後記500封到千信加退款
別讓網站當掉
隨時全部一萬筆訂單要好的多
但他們還是需要超快速的處理庫存
這裡才是真正精彩的地方
假設你的訂單裡面有PS5一件
T-SYH還有一本書
一個FuLink處理器從主要的Cuff Car註列裡
把你的訂單拉出來
把它拆成三個獨立的訊息
然後把這三個訊息分別丟進
依照商品ID嚴格分區的四級Cuff Car註列
這裡是整個設計的靈魂所在
依照商品ID分區
意思是
全世界所有關於PS5的訂單
都會被數學上路由到同一個Cuff Car分區
然後由同一台FuLink似乎企業來消化
為什麼這很重要
因為所有一萬筆PS5訂單
現在都按照順序達到同一台機器上
這台機器不需要去溫任和資料庫
不需要鎖定
它把庫存數量比方說500
直接放在自己的本地記憶體
它就在記憶體裡面倒數
599、498
它每秒可以處理幾百萬格這樣的操作
名網路延遲
靈靜真條件
當本地記憶體的技術規定
這台FuLink似乎企業
就把助列以剩下的9500筆訂單
標記為缺貨
非同步的觸發推款流程
技術道歉性
然後每個十分鐘
FuLink似乎企業把最新的庫存數量協回
主要的MangoDB資料庫
一次一個P-S 更新
這邊的取捨很深刻
你放棄了資料庫鎖定的安全感
接受偶爾會超賣的可能性
但換來的是無限的水平擴展能力
也就是說系統可以隨著需求增加
無限的擴充處理能力
你把一個超複雜的分散
是並發協助問題
變成了一個簡單的單紙形式的
本地記憶體到處問題
所謂單紙形式就是說
這台機器一次子專心處理一個任務
這樣就不用擔心
多個任務搶資源的問題
我打的比方
就像你把一個
需要全體員工開會才能做的決定
改成讓一個人負責記憔
其他人繼續做事
事後再對掌
效率添查地緣
有時候解決資料庫平均最好的方法
不是更好的技術
而是改變產品需求
透過跟業務端協商接受最終移植性
跟退款機制
你就能解鎖一個
可以撐住任何流量高峰的架構
好到這邊我們把整個購買流程走完了
但還有一個很有趣的情境
那些沒搶到的使用者
收到道歉信之後
他們想知道
PS5什麼時候補貨
或是什麼時候降價
這就帶出了第四個生前主題
價格降價通知與大規模廣播問題
問題是
當一個商品降價
你怎麼在幾秒內
通知100萬個訂閱這個商品的擁護
最直覺做法是
讓流氮氣定時去溫室服氣
你在前端協議端程式
每60秒就溫宜次伺服氣
價格很弱變,聽起來很簡單
但我們來算一下數字
如果有1000萬個使用者在線上每分鐘問一次
那就是每秒大約16000個見面請求
達到你的伺服器
而且其中99%點久的時候
價格根本沒有變
伺服器只是回答沒有
你再用大量的計算資源跟網路頻換
來處理完全沒有意義的流量
那用Webサー坑的前面說過
WebSocket是讓手機和伺服器保持即時雙向連線的技術
但維持1000萬條開折的WebSocket連線
只是為了一週可能才發生一次的降價通知
這個成本根本不合理
WebSocket是設計給聊天時
或多人遊戲這種資料一直在來回傳送的狀況
不是為了這種偶爾才需要推播一次的通知
真正適合這個情境的技術叫做Severalcentibans 檢稱SSC
就是一種伺服器主動推播給流覽器的單項廣播技術
流覽器連線一次說我在停
連線就保持開折
但幾乎不小好任何資源
伺服器只有在真的有事情發生的時候
才會把資料推播下去
但伺服器怎麼知道什麼時候廣播
又是我們的老朋友CDC
當賣家在主要資料庫更新PS5的價格
資料庫發出一個CDC事件
這個事件被丟進訊息註練
接下來面對的是大規模廣播問題
你要把一個單一事件
也就是價格變了擴散成100萬個個別任務
也就是通知100萬的使用者
如果讓一個後南工作層次接到這個CDC事件
然後試圖一次重資料庫
拉出全部100萬的訂閱者
這個層次會直接因為記憶體不足的崩潰
100萬比使用者資料根本塞不進記憶體
所以他們用的是一個串聯的註練系統
第一批背景工作層次接到價格變動的事件
它不是一次腦全部
而是用分業的方式先拿錢1000個訂閱者
把這1000個使用者丟進第二個通知註練
再拿接下來的1000個再丟進去
以此類推
然後有一大批第二層的背景工作層次
從那個通知註練裡面拿小批次的使用者
把通知透過開展的SSC連線推播下去
他們還加了一個門檻直過濾的機制
如果賣價把價格從499元改成498.99元
系統會抓到這個只差一分錢的變動
直接把這個事件經末丟起
完全不觸發大輪廣播
只有當價格下降幅度達到一定百分比
才會真的啟動整個通知流程
你看看是不是很聰明
這邊的取捨就是價格會比較複雜
你需要管理CDC管線多個訊息註練
分業的背景工作層次還有SSC連線群
只是為了傳送一個降價通知的提示
但這是唯一能在不脫垮似乎氣的情況下
把一個事件廣播給100萬的使用者的方法
所以螺連線協定要跟資料流向匹配
如果用路段不需要回程資料
就不要用WebSock可以用SSC就好
而且在對G8案的使用者做任何操作之前
永遠要用分業的方式來查詢資料庫
聽到這邊你可能覺得這個系統已經很完整了
但在系統設計裡面最重要的問題
從來不是它怎麼運作
而是它壞掉的時候怎麼辦
我們來壓力測試一下
如果快取成整個掛掉會怎樣
前面提到我們用Redis來存熱門搜尋結果的快取
以及購物車的贊存狀態
Redis是一個把資料完全存在記憶體列的快取系統
只讓它速度超快
但記憶體是會發信的
如果資料中心發生電源故障
Redis從起記憶體列的東西就全部進空了
如果系統完全依然Redis來存購物車
一次崩潰就代表幾百萬個使用者的購物車瞬間變空
他們去結帳東西全部建了
這是一個災難性的使用者體驗
使用者體驗是系統採用一個叫做雙重協入的模式
當使用者把東西加進購物車系統同時協入兩個地方
一個是快速的Redis快取
另一個是存在固態應點上的持久化SQL資料庫
這個SQL資料庫就是我們前面說的
用來儲存購物車權為資料的地方
正常運作的時候系統只從Redis獨快有順
但如果Redis崩潰記憶體被清空
應用程式似乎其實偵測到Redis掛了
馬上把所有獨取請求切換到那個比較慢的
SQL資料庫延遲會上升
往債會感覺比較慢
夜面載入時間可能從100毫秒跳到800毫秒
但只要是安全的
使用者不會失去他們的購物車
等Redis崩潰之後
一個背景腳本會慢慢從SQL資料庫
把快取重建起來
系統就自己恢復了
這個過程我們就稱之為降機
雖然慢一點但至少還能用
這就是龍挫設計的本質
你假設硬體一定會壞
然後你提前建好一條
降機大還能用的被源入境
對了今天參考的幾支院實驗
片我都有放在資訊欄
如果你想看更完整的內容
可以直接點過去看
最後我們來把這個
龐大的架構整理成幾個
你可以帶進編勢
或帶進工作的核心觀念
如果你在面試背問到設計一個電商平台
你的第一句話應該是
我會把讀取為主的商品幕錄
跟協入為主的交易系統分開
因為他們需要根本上
不同的資料庫
光是這句話
就能讓面試管知道
你有架構思維
然後你需要避開
三個常見的面試線境
第一個是範圍管理
面試管說設計Amazon
它不是要你在
45分鐘內設計推薦引擎
LWS基礎設施
評論系統跟物流配送
你要主動縮小範圍
聚焦在核心流程
搜尋購物車結帳
把背景交太清楚
讓面試管知道你理解要怎麼管理這個範圍
第二個是
SQL跟NOSQL的面試
很多人覺得
十一個使用者就一定要用
NOSQL
因為它比較能水平擴展
也就是說
當資料量增加
可以透過增加機器
來擴充處理能力
這其實是個陷阱
SQL資料庫透過SR頂
也就是把一個大資料庫
切成好幾塊分開存放
一樣可以水平擴展
你選NOSQL來存商品墓入
真正的理由是
資料覽會彈性
繼續跟筆電的屬性完全不同
但對於訂單跟金融交易
觀點是SQL資料庫
因為嚴格的資料完整性保證
往往還是更好的選擇
第三個也是最重要的是
理解什麼時候不應該用原子操作
一個好的面試者
會用資料庫鎖定來防止朝買
一個很好的面試者會意識到
鎖定會摧毀系統的處理速度
然後引入CovCar跟
串流處理的架構
並且明確說出這個商業趨勢
我們接受最終一致性
跟Ovo推款
換取在流量高峰時的
高可用心
這個模式把一個慢速
會有競爭的操作
從介面回應裡面切除去
放進助列在背景處理
其實到處都在用
就算你不是在建下一個電廠平台
只要你要使用著
車時間丟進助列來
非常不推薦歡迎性
而不是讓使用著等待信件似乎
回應
你用的就是同樣的概念
回到最開頭的問題
Mas人怎麼在三秒內
讓你找到商品保住你的購物車
然後出令的訂單
他的方法是
永遠不依賴單一的資料來源
他用搜尋所引來換速度
用數學上的CRDT
來解決衝突
用事件串流
變成有秩序的序列處理
下次你按一下加入購物車
感覺好像瞬間完成的時候
你就知道背後有多少個資料庫
助列跟串流處理器正在同時運作
才能讓這個瞬間看起來這麼離手當然
覺得今天拆解電商平台的架構
讓你有點收貨嗎
那就幫我到Apple Park S3 站著一種
柳哥無心好平吧
如果你有想聽我的拆解那款
Apple也歡迎去FB
Ig或Fresh Soul
AI藍人報視訊跟我說
你的支持就是我繼續把節目
優化的最大動力
在這個AI時代學會怎麼設計系統
真的比學 扣更關鍵
別忘了訂閱AI藍人報
我們每集系統設計藍藍學
都會帶你拆解一個大架構
我是唐人藍
下次見掰囉
Podcast Summary
Key Points:
- 核心挑战: 电商平台需同时满足闪电般的搜索速度、银行级的交易精确性,并支撑全球数亿用户并发访问,这是系统设计的根本矛盾。
- 架构核心原则: 将单一应用拆解为多个独立系统(分离原则),并为搜索、购物车、结账等不同功能使用专门的数据库和技术。
- 搜索(读取优化): 使用ElasticSearch的倒排索引和Redis缓存来处理PB级商品数据的毫秒级搜索,将搜索从主数据库中剥离。
- 购物车(高并发写入): 采用多主复制架构和CRDT数据结构,通过存储操作记录而非最终状态,从根本上解决多设备并发写入导致的数据覆盖问题。
- 结账(库存与一致性): 放弃悲观的数据库锁定,采用事件驱动架构(Kafka + Flink),将订单接收与库存扣减分离。通过按商品ID分区,将并发问题转化为单机内存计数问题,以接受超卖和退款换取高可用性。
- 通知(大规模广播): 使用SSE(服务器发送事件)和CDC(变更数据捕获)实现高效的降价通知,并通过分页处理和阈值过滤避免资源浪费。
- 容错设计: 采用双重写入策略(Redis + SQL数据库),当缓存崩溃时系统降级但可用,确保用户购物车数据不丢失。
Summary:
这段视频深入剖析了支撑大型电商平台(如亚马逊)在“黑色星期五”等极端流量下的系统架构。核心思想是**分离原则**,即将一个看似统一的电商网站拆解为多个独立的子系统,每个子系统针对其核心任务进行优化。
首先,针对**商品搜索**,系统不会直接查询庞大的主数据库,而是使用ElasticSearch构建倒排索引,并利用Redis缓存热门搜索结果,实现毫秒级响应。其次,面对**购物车**的高并发写入挑战,系统放弃了传统的数据库锁,采用多主复制架构和CRDT(无冲突复制数据类型)数据结构。CRDT不存储购物车的最终状态,而是存储一系列带唯一ID的操作记录,从而在数学上保证来自不同设备的并发操作不会互相覆盖,即使有毫秒级的同步延迟。
最关键的**库存管理**环节,系统采用了反直觉的设计:将接收订单与扣减库存完全解耦。通过Kafka和Flink构建事件驱动流,当用户下单时,系统立即接受订单并丢入消息队列,而非立即查询库存。所有针对同一商品的订单会被路由到同一个Flink处理单元,该单元在本地内存中进行原子级的库存递减,避免了数据库锁带来的性能瓶颈。这种设计接受了“先卖后道歉”(即超卖后退款)的商业策略,换取了系统在流量洪峰下的超高可用性。
此外,系统还通过CDC(变更数据捕获)触发降价通知,并使用SSE(服务器发送事件)进行高效的大规模广播。在容错方面,采用双重写入策略,确保缓存崩溃时数据不丢失,系统仅降级运行。整个架构的哲学在于:永远不依赖单一数据源,通过分离、异步、事件驱动和数学保证(如CRDT),将复杂的分布式问题转化为可控的本地问题。
FAQs
它使用倒排索引和專用搜尋引擎Elastic Search,並透過CDC(資料變動捕捉)從主要資料庫同步更新,避免直接查詢龐大的資料庫。
系統採用CRDT(無衝突複製資料型別)儲存操作記錄而非最終狀態,並使用多主節點複製資料庫,確保並發操作不會互相覆蓋。
系統將接收訂單和扣減庫存分離,使用Kafka和Flink串流處理,按商品ID分區讓單機本地記憶體倒數庫存,接受超賣並退款以保持高可用性。
使用SSE(伺服器推送事件)單向廣播,搭配分頁查詢和串聯訊息佇列,並設價格變動門檻過濾,避免無效通知。
不會。系統採用雙重寫入模式,同時將資料存入Redis快取和持久化SQL資料庫,Redis崩潰時切換到SQL資料庫,確保資料安全。
核心原則是分離讀取為主的商品目錄和寫入為主的交易系統,使用不同資料庫,並透過事件驅動架構處理並發問題。