skr shop是一羣底層碼農,因爲被工做中的項目折磨的精神失常,加之因爲程序員的自傲:別人設計的系統都是一坨shit,個人設計纔是宇宙最牛逼,因而乎決定要作一個只設計不編碼的電商設計手冊。
項目地址:https://github.com/skr-shop/m...前端
對於一個電商來說,購物車是整個購買流程最重要的一步。由於電商發展到今天購物車不只僅只是爲了完成打包下單的功能;也是收藏、對比、促銷提醒、相關推薦的重要展現窗口。如此多的能力咱們該如何設計保證購物車的高性能、以及良好的擴展能力來知足將來的發展呢?git
今天開始咱們就以一個假定的場景來輸出一個購物車設計:某某電商平臺,是一個多租戶模式(咱們前面的諸多設計都是多租戶模式),用戶能夠把商品加入到購物車,並切按照商戶緯度來展現、排序。固然購物車也支持常規的各類操做:選擇、刪除、清空、商品失效等。而且有相關的促銷可以提醒用戶。同時爲了監控、運營,要支撐購物車數據同步到監控、數倉等能力。程序員
本文會從用戶使用的角度以及服務端兩個角度來說解系統的能力。本篇咱們的主要目的是說清楚購物車的能力以及一些邏輯。下一篇會進行購物車模型設計以及接口定義。github
咱們先來定義一下在用戶側用戶操做購物車的功能有哪些?後端
一個購物車基本的能力基本上都在上圖中,下面咱們一一來分解。網絡
咱們從用戶的角度來看,購物車對於用戶來講能夠添加商品到購物車(加購物車、當即購買都屬於一種添加方式);加入進購物車後,不想要了能夠刪除該商品(刪一個、刪多個、清空);想多買能夠修改購買數量,發現錢不夠能夠減小購買數量;或者發現紅色的比白色更漂亮,能夠在購物車方便的進行更換規格;對於一些價格很貴的商品,可以在購物車添加一些保障服務(實際上是綁定的虛擬商品);在要去結算的時候,還會提供選擇能力讓用戶決定哪些商品真的本次要購買。數據結構
經過上面的描述咱們能夠看到這個過程是有其內在聯繫的。這裏說一下關於選中功能,業界有兩種作法,各有優劣,咱們來看一下。淘寶的產品選中狀態是保存在客戶端的,而且默認不選中,刷新、從新打開APP狀態會消失;京東、蘇寧這一類是保存在服務端,會記錄用戶選中狀態。針對這兩種狀況各有優劣。併發
客戶端:異步
服務端:性能
我的認爲這兩種方式並沒有誰具有明顯優點,徹底是一種基於業務模式以及團隊狀況來作選擇。咱們這裏後續的設計會基於在服務端保存商品選中狀態。
在整個操做邏輯中,有個兩個比較重要的地方單獨說明一下:購買方式與購物車內修改購買屬性
主要的購買方式有當即購買、加入購物車、拼團購三種方式。
首先普通的加入購物車沒什麼太多要說的。重點來看下當即購買與拼團。
當即購買在於操做上來講就是選擇商品後直接到了訂單確認頁面,沒有購物車中去結算這一步。可是它的實現卻能夠依賴購物車的邏輯來作,咱們來看一下使用購物車與不使用購物車實現這個邏輯有什麼差異?
若是使用購物車來實現,也就是用戶點擊當即購買時,商品本質上仍是加入到購物車中,但這個購物車卻與原型的購物車不一樣,由於該購物車只能加一個商品,而且每次操做都會被覆蓋。在視角效果上也是直接從商品詳情頁面跳轉到訂單確認頁面。來看看這種方式的好處
另一種實現方式使用一個新的數據結構,由於通常來講一鍵購買更簡單,它只須要商品信息、價格信息便可。每次交互都可以根據sku_id來獲取。
咱們會採用使用在服務端一鍵購買以獨立的購物車形式來實現。購物車的數據模型一致,保證了後續處理流程上的一致。
對於拼團,他其實分爲兩部分,首先是開團這個動做,當團成立後。咱們能夠選擇將成團的商品加入普通購物車,同時能夠加購其它商品。也能夠選擇將成團商品加入一鍵購買的購物車,保證成團商品只能買一個。拼團模式更像是加入購物車的一個前置條件。本質上它對於購物車的設計沒有影響。
這裏主要是指能夠在購物車便捷的操做一些須要在spu緯度操做的事情,好比:變動規格(也就是更換sku),以及選擇綁定到spu緯度的服務(保險、延保等)。
咱們重點說一下選擇綁定的服務。例如:咱們買一個手機,廠家提供了延保、各類其它附加服務,通常狀況這種服務都是虛擬商品。可是這有個特殊狀況。這些保障服務首先不能單獨購買,其次他是跟主商品的數量息息相關。好比買兩個手機,若是選擇了加購服務,那麼這些服務的數量必須是2,這會是一個聯動關係。
這些保障服務是不能進行單獨購買的,它必定要跟特定的商品捆綁銷售。
服務端在存儲這部分數據時必定須要考慮如何保存這種層級關係,這部分咱們後面模型設計的時候你們會看到。
促銷提醒很簡單,返回的購物車數據,每個商品應該攜帶當前的促銷信息。這部分重點在於怎麼獲取促銷信息,會在服務端看到。
而後說下購物車數量的提醒,也就是顯示當前購物車商品的數量。通常來講進入到APP就會調用一個接口,獲取用戶的未讀消息數、購物車商品數等。這裏是須要很是高的讀取速度。那麼這種需求該如何知足呢?
方案一: 咱們能夠設計一個結構保存了用戶相關的這種提醒信息數量,每次直接讀取這個數據便可。不須要去跟消息服務、購物車服務打交道拿這些數據。
方案二: 在消息、購物車的模型中均設計一個保存總數量的字段,在讀取數據的接口中,經過併發的方式調用這些服務拿到數據後進行聚合,這樣在速度上只取決於最慢的服務。
這裏咱們的設計會採用 方案二,由於這樣在某種程度上效率能夠獲得保證,同時整個系統的結構數據的一致性更容易獲得保障。固然這裏有個細節必定要注意,併發讀取必定要設計超時,不要由於某個服務讀數問題而致使拖累整個接口的性能。
接下來再來看看促銷,這部分除了提醒,還須要提供對應的入口,讓用戶完成促銷的操做。好比說某個商品有券,那麼能夠直接提供入口去領取;可湊單,有入口進入湊單列表並選擇商品等。這部分須要解決的問題是服務端該如何及時從商品緯度拿到這些促銷活動。
從用戶的視角看完了,咱們再來站在研發的角度看看服務端有哪些事情要作
仍是先來看看需求的彙總圖:
對於存儲,首選確定是內存存儲,至於要不要落庫,我以爲沒有必要。說下個人理由:
因此對於購物車,咱們只會把數據徹底保存在內存中。
如今咱們來討論 商品銷售類型發生變化 這個問題。這是什麼意思呢?你們想一下:好比我把A商品加入到購物車,可是一直沒有結算。這時運營說針對A商品搞一個活動,拿出10個庫存5折購。那麼問題來了,對於以前購物車中就有該商品的用戶該如何處理?這裏解決的主要問題是:購物車有該商品的用戶不能直接以5折買。幾種方案,咱們來看一下:
方案一: 促銷配置後,全部購物車中有該商品的用戶失效或刪除,這個方案首先被pass,操做成本過高,而且用戶體驗差
方案二: 購物車中要區分同一個SKU,不一樣銷售類型。也就是說在咱們的購物車中不是按照SKU的緯度來加商品,而是經過 SKU+售賣類型 來生成一個惟一識別碼。
能夠看到 方案二 解決了同一個sku在購物車並存的問題,而且庫存以前互相不影響。不過這裏又有一個問題?商品的售賣類型(或者說這個標記),該怎麼什麼地方設置?好像商品系統能夠設計、促銷系統也能夠設置。咱們的邏輯中會在促銷系統中進行配置。由於商品屬於基礎邏輯,若是一改就是全局庫存受到影響。活動結束後很難作到自動正常售賣。所以這個標記應該落到活動中進行設置(活動設置時會經過促銷系統獲取該商品以前的活動是否互斥,以確保配置的活動不會互相矛盾)。
購物車系統依賴了很是多的其它系統。
這些依賴的系統,有的是爲了傳輸數據,有的是爲了獲取數據。咱們按照這兩個緯度來看一下。
服務端要解決的是促銷的提醒與價格計算問題。
現來講計算,針對這部分最佳的方式是,調用結算中心的價格計算。咱們來看一下購物車中的價格計算與訂單結算時的價格計算的差別。
首先購物車中計算價格時不知道用戶的地址,這會影響運費的計算;再是不知道用券的狀況。那麼其實若是解決了這兩個問題,咱們就可讓價格計算出自同一個邏輯,僅僅是部分入參不一樣罷了。所以咱們這裏計算時能夠按照最高運費來計算,同時用券默認在購物車都不使用券。對於促銷問題這裏是能夠經過促銷系統確認選中的商品能夠享受哪些價格的。所以促銷的價格應該計算在內。
接下來在再來講說如何爲用戶高效的提供促銷的信息。先從咱們的配置視野出發。
咱們在配置一個促銷活動或者發一張券時,都是將多個商品歸到一個促銷活動或者券的下面。若是按照活動、券的緯度來獲取商品效率相對比較高。
可是在購物車的場景中發生了一個變化。咱們是須要從商品緯度獲取到該商品的全部活動信息(全平臺活動、店鋪活動);
那麼購物車中爲了展現這些信息該怎麼作?很常規的一個作法(也確實很多公司是這樣):把全部活動信息取出來,遍歷出全部跟該商品相關的信息。這種作法效率很低,而且沒法知足大規模的應用場景,好比雙十一期間。
所以這裏爲了知足該需求,促銷系統須要提供一個能力按照商品獲取對應促銷(活動、券)。所以通常來說促銷系統配置的活動不能僅僅是按照活動緯度存儲,同時還須要生成一份商品緯度的促銷信息。
對於購物車數據來講,前端會經過埋點記錄加入購物車數據的狀況,可是前端埋點通常是記錄觸發了某個前端操做,可是並不知道該操做是否成功與否。以及沒法及時瞭解當前總體購物車的數據狀況。
爲了讓運營團隊更完整的瞭解購物車當前狀況,咱們經過後端打本地日誌,而後經過日誌收集的方式將日誌同步給數據、監控等服務。
還有兩個小部分沒有講到,一是商品該如何失效,好比:庫存沒有了、下架了;二是購物車中的商品是多個店鋪的,排序的策略是什麼?
因爲本文咱們還只是討論需求,不涉及具體的模型設計,所以只是介紹方案。首先是商品失效,這很像一個軟刪除操做,一旦設置,用戶側看到的商品將是沒法進行結算的,只能進行刪除操做。
對於排序咱們會採用的設計是:根據某個店鋪在購物車中最後發生操做的時間,最新的操做確定在最上面。
經過上面咱們基本上搞清楚了購物車設計中咱們要作什麼,依賴的系統要提供什麼能力。下篇開始進入數據模型的設計、先後端接口設計。
若是你對購物車上面的需求還有哪些補充,歡迎留言。咱們一塊兒來完善。