星巴克是如何處理訂單的?
點擊上方藍色“程序猿DD”,選擇“設為星標”
回復“資源”獲取獨家整理的學習資料!


來源:r6d.cn/6dyh
譯者序
本文翻譯自 2004 年的一篇文章: Starbucks Does Not Use Two-Phase Commit.
1. 請給我一杯熱巧克力(Hotto Cocoa o Kudasai)
剛結束了一次為期兩周的日本之旅。印象深刻的是數(shù)量多到難以置信的星巴克 —— 尤其是在 新宿和六本木地區(qū)。在等待咖啡制作時,我開始思考星巴克是如何處理訂單的。
與大多數(shù)商業(yè)公司一樣,星巴克主要關心的也是訂單最大化。更多的訂單就意味著更多的收入。因此,他們采用異步的方式處理訂單:
點好咖啡后,收銀員會拿出一個杯將你的訂單在杯子上做個標記,然后將杯子放到一個隊列。這里所說的隊列其實就是咖啡機上的一排杯子;
隊列將收銀員和咖啡師解耦,使收銀員能夠不斷接單,即使咖啡師已經(jīng)有點忙不過來了。
在這種方式中,如果咖啡師真的忙不過來了,可以再加幾個咖啡師。這就是所謂的 Competing Consumer 場景。
2 關聯(lián)
享受異步帶來的好處的同時,星巴克也需要解決異步方式內(nèi)在的挑戰(zhàn)。例如,關聯(lián)(correlation)問題。
咖啡制作完成的順序不一定與下單的順序一致。這有兩個可能的原因:
多位咖啡師可能在分別使用不同的咖啡機同時制作。另外,不同類型的咖啡所需的 時間也不同,例如調(diào)配型咖啡會比已經(jīng)磨好、拿杯子直接接就行的咖啡所花的時間要長;
咖啡師可能會將同一咖啡類型的多個訂單放到同一批制作,以節(jié)省整體的制作時間。
因此,星巴克會面臨咖啡與顧客之間的關聯(lián)問題??Х戎谱魍瓿傻捻樞蚴遣淮_定的,需 要將每一杯咖啡分別對應到正確的顧客。星巴克解決這個問題的方式與我們在消息系統(tǒng) 中所使用的“模式”是一樣的:使用某種關聯(lián) ID。
在美國,大部分星巴克都會將顧客的名字作為顯式關聯(lián) ID 寫到杯子上,咖啡制作完成后服務員會叫顧客的名字;
在其他國家,可能會用咖啡的類型來做關聯(lián)(例如,服務員會喊:“大杯摩卡好了”)。
3. 異常處理
異步消息系統(tǒng)中的異常處理是很困難的。如果說現(xiàn)實世界中已經(jīng)很好的解決了這個問題,那我們可以通過觀察星巴克如何處理異常學到一些東西。
如果付款失敗,他們會怎么做?
如果咖啡已經(jīng)做好了,他們會倒掉;
如果還沒有開始做,他們會將杯子從“隊列”中拿走。
如果咖啡做錯了,或者對咖啡不滿意?他們會重新做一杯;
如果咖啡機壞了,做不了咖啡?他們會退款。
這些場景分別描述了幾種常見的錯誤處理策略。
3.1 銷賬
這是所有錯誤處理策略中最簡單的:什么都不用做,或者丟棄已經(jīng)做的所有東西。
聽起來似乎不靠譜,但實際業(yè)務中,有時這種方式是可接受的。如果銷賬帶來的損失很小, 那相比斥巨資實現(xiàn)一種復雜的錯誤處理機制,銷賬的方式還是更劃算的。
例如,我曾為多家因特網(wǎng)服務提供商(ISP)工作,在他們的業(yè)務中,如果計費發(fā)生錯誤,他們就會選擇銷賬的方式。其導致的結果是,客戶可能會 享受了某些服務,但沒有被收費。
這種處理方式給他們帶來的營業(yè)損失足夠小,因此業(yè)務能夠保持運營。另外,公司會定期地對賬,主動檢測這些“免費”賬戶并將其關閉。
3.2 重試
當一大組操作(例如一次事務)中的某些操作失敗時,我們基本有兩種選擇:
回退已完成的操作;
重試失敗的操作。
如果重試有較大的概率能成功,那就可以考慮重試方式。例如,
如果失敗的原因是違反了業(yè)務規(guī)則,那重試就不太可能會成功;
如果失敗的原因是某個外部系統(tǒng)掛了,那重試就有可能會成功。
這里有一種特殊的重試:冪等接收器重試(retry with Idempotent Receiver)。在這種場景中,我們可以簡單地重試所有操 作,因為接收器成功之后便會忽略重復的消息。
3.3 補償
最后一種方式是回退所有已完成的操作, 讓系統(tǒng)回到一致的狀態(tài)。例如,在金融系統(tǒng)中,這些“補償動作”能在交易失敗時對已扣款進行退款處理。
4. 兩階段提交
以上所有策略都與兩階段提交不同。兩階段提交包含前后兩個步驟:
準備階段;
執(zhí)行階段。
如果在星巴克中使用兩階段提交,那買一杯咖啡的過程將變?yōu)椋?/span>
準備階段:前臺點單,打印小票,然后將現(xiàn)金和小票都放到臺面上,等待咖啡做好;
執(zhí)行階段:咖啡做好后,現(xiàn)金、小票和咖啡同時易手,完成交易。
在“事務”完成之前,收銀員和顧客都不能離開。
顯然,如果使用這種提交方式,星巴克的業(yè)務量將急劇下降,因為相同時間內(nèi)能服務的 顧客數(shù)量將銳減。
這個例子也提醒我們,兩階段提交會讓生活變得加更簡單(因為錯誤處理非常簡單),但它也會妨礙消息的自由流動(以及自由流動帶來的可擴展性),因為它必須將多個異步操作封裝成一個有狀態(tài)事務。
5. 會話模式
咖啡店交互的過程其實也是一個簡單但很常見的 Conversation 模式的例子。
雙方(顧客和咖啡店)之間由兩次交互組成:
時間較短的同步交互:完成下單和支付;
時間較長的異步交互:完成咖啡的制作和交付。
這種類型的會話在電商場景中是非常普遍的。例如,在 Amazon 買東 西時,時間較短的異步交互過程會分配訂單號,而所有的后續(xù)步驟(信用卡扣款、打包、配 送)都是異步完成的。這些額外的異步步驟完成后,你會收到郵件方式(異步)的通 知。如果中間發(fā)生任何差錯,Amazon 通常會進行:
補償:退款到信用卡;
重試:補發(fā)配送過程中丟失的物品。
可以看到,真實世界往往都是異步的。我們的日常生活是由許多協(xié)調(diào)但異步的過程組成的,例如讀取和回復電子郵件,購買咖啡等等 。這意味著,異步消息模型通常能很自然地對這些類型的交互進行建模。
此外,這還意味著,經(jīng)常觀察日常生活有助于設計出成功的消息系統(tǒng)。
感謝閱讀!
原文鏈接:https://www.enterpriseintegrationpatterns.com/ramblings/18_starbucks.html
?
往期推薦
掃一掃,關注我
一起學習,一起進步
每周贈書,福利不斷
﹀
﹀
﹀
深度內(nèi)容
推薦加入
最近熱門內(nèi)容回顧? ?#技術人系列

