Go back

EP371 | 系統設計懶懶學 – Amazon 電商架構大揭密:如何處理每日 1 億筆訂單的並發衝突與庫存管理?深入搜尋引擎架構,學會倒排索引與快取降級策略。

28m 37s

EP371 | 系統設計懶懶學 – Amazon 電商架構大揭密:如何處理每日 1 億筆訂單的並發衝突與庫存管理?深入搜尋引擎架構,學會倒排索引與快取降級策略。

这段视频深入剖析了支撑大型电商平台(如亚马逊)在“黑色星期五”等极端流量下的系统架构。核心思想是**分离原则**,即将一个看似统一的电商网站拆解为多个独立的子系统,每个子系统针对其核心任务进行优化。 首先,针对**商品搜索**,系统不会直接查询庞大的主数据库,而是使用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:

  1. 核心挑战: 电商平台需同时满足闪电般的搜索速度、银行级的交易精确性,并支撑全球数亿用户并发访问,这是系统设计的根本矛盾。
  2. 架构核心原则: 将单一应用拆解为多个独立系统(分离原则),并为搜索、购物车、结账等不同功能使用专门的数据库和技术。
  3. 搜索(读取优化): 使用ElasticSearch的倒排索引和Redis缓存来处理PB级商品数据的毫秒级搜索,将搜索从主数据库中剥离。
  4. 购物车(高并发写入): 采用多主复制架构和CRDT数据结构,通过存储操作记录而非最终状态,从根本上解决多设备并发写入导致的数据覆盖问题。
  5. 结账(库存与一致性): 放弃悲观的数据库锁定,采用事件驱动架构(Kafka + Flink),将订单接收与库存扣减分离。通过按商品ID分区,将并发问题转化为单机内存计数问题,以接受超卖和退款换取高可用性。
  6. 通知(大规模广播): 使用SSE(服务器发送事件)和CDC(变更数据捕获)实现高效的降价通知,并通过分页处理和阈值过滤避免资源浪费。
  7. 容错设计: 采用双重写入策略(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資料庫,確保資料安全。

核心原則是分離讀取為主的商品目錄和寫入為主的交易系統,使用不同資料庫,並透過事件驅動架構處理並發問題。

Chat with AI

Loading...

Pro features

Go deeper with this episode

Unlock creator-grade tools that turn any transcript into show notes and subtitle files.