日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

库存系统难破题?京东到家来分享

發(fā)布時間:2025/4/5 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 库存系统难破题?京东到家来分享 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

http://www.sohu.com/a/194461959_467759

目前,京東到家?guī)齑嫦到y(tǒng)經(jīng)歷兩年多的線上考驗與技術(shù)迭代,現(xiàn)服務(wù)著萬級商家、十萬級店鋪的規(guī)模,在需求變更與技術(shù)演進中,如何做到系統(tǒng)的穩(wěn)定性與高可用?下面將會給你揭曉答案。

庫存系統(tǒng)技術(shù)架構(gòu)

庫存系統(tǒng)技術(shù)架構(gòu)圖

上圖如果進行總結(jié)下,主要體現(xiàn)出以下幾個方面:

完善的基礎(chǔ)設(shè)施

強大的基礎(chǔ)服務(wù)平臺讓應(yīng)用、JVM、Docker、物理機所有健康指標一目了然,7*24 小時智能監(jiān)控告警讓開發(fā)無須一直盯著監(jiān)控;

數(shù)據(jù)驅(qū)動

數(shù)據(jù)與業(yè)務(wù)相輔相成,用數(shù)據(jù)驗證業(yè)務(wù)需求,迭代業(yè)務(wù)需求,讓業(yè)務(wù)需求都盡可能的收益最大化,庫存系統(tǒng)的開發(fā)同學(xué)只需要關(guān)注業(yè)務(wù)需求;

健全的測試團隊

大版本上線前相應(yīng)的測試同學(xué)會跟進壓測,防止上線后潛在的性能瓶頸。

庫存系統(tǒng)技術(shù)架構(gòu)圖解釋說明

Portal

通過提供商家 PC 端、App 端解決大部分中小商家的日常運營需求,另外提供開放平臺滿足大中型商家系統(tǒng)對接與數(shù)據(jù)共享互通的問題。

Service

這個板塊涵蓋了整個庫存最核心的 C&B 數(shù)據(jù)業(yè)務(wù)。

1、業(yè)務(wù)類

  • C 正常流程:用戶下單 - 商家揀貨 - 快遞員妥投

  • C 異常流程 - 缺貨:用戶下單 - 商家缺貨 - 用戶協(xié)商 - 調(diào)整訂單缺貨商品 - 商家揀貨 - 快遞員妥投

  • C 異常流程 - 取消:用戶下單 - 用戶反悔 - 訂單取消

  • C 異常流程 - 風控:用戶下單 - 風控攔截 - 訂單鎖定 - 客服審核 - 訂單取消 / 繼續(xù)生產(chǎn)

  • B 正常流程:商家維護可售庫存數(shù)量,即時或者定時生效

2、數(shù)據(jù)類

除了業(yè)務(wù)類需求外,京東到家還提供了大量有商業(yè)價值的數(shù)據(jù)供商家作業(yè)務(wù)決策,比如:

  • 商品銷量 Top 榜 - 支持分城市分類目篩選

  • 熱銷商品庫存不足預(yù)警 - 商家 App 版本 Push 通知及待辦事項中可以醒目識別這部分商品并進行維護

  • 紅黃線自動下架 - 近七日訂單量大于 5 單,并且被踩率大于等于 20% 的商品,進行下架操作,每日執(zhí)行。

  • 庫存交易流水

3、中間件類

古人行軍打仗,兵馬未動,糧草先行,對于系統(tǒng)來說亦是如此,編碼未動架構(gòu)先行,架構(gòu)的技術(shù)選型非常重要,在這里給大家分享京東技術(shù)體系上萬碼農(nóng)都在使用的幾個中間件。

  • JSF,類似于 DUBBO, 是一款非常優(yōu)秀的 RPC 層框架,可以解決應(yīng)用間的數(shù)據(jù)通信問題,它最主要的優(yōu)勢是長連接的實現(xiàn)以及高效的序列化組件。

  • JMQ,JMQ 是京東自主研發(fā)的一款消息中間件系統(tǒng),具有高可用、數(shù)據(jù)高可靠等特性。廣泛應(yīng)用于公司內(nèi)部系統(tǒng),包括訂單、支付、庫房、交易等場景。在庫存系統(tǒng)中會優(yōu)先更新 Redis 緩存數(shù)據(jù),并發(fā)送變更 MQ,供 MySQL 及 ES 異步更新。

  • O2OWORKER,早期淘寶開源的一款產(chǎn)品 TBSCHEDULE,不這個只適用于單項目管理,多個系統(tǒng)使用的話權(quán)限無法隔離,另外參數(shù)配置過于繁瑣,結(jié)合這兩點進行了重構(gòu),從而形成了現(xiàn)在的整個京東到家都在使用的任務(wù)管理平臺。

DB

1、MySQL

京東到家?guī)齑嫦到y(tǒng)使用的關(guān)系型數(shù)據(jù)庫是 MySQL,低成本、低耦合、輕量級,總之優(yōu)勢多多。

2、Redis

豐富的數(shù)據(jù)結(jié)構(gòu) & 眾多的原子性命令支持,非常適合庫存系統(tǒng)進行緩存查詢及扣減操作。

3、ES

庫存系統(tǒng)的數(shù)據(jù)量非常大,首先 MySQL 數(shù)據(jù)庫通過水平擴容來解決單表數(shù)據(jù)量過大的問題,水平擴容的規(guī)則采取的是按門店維度進行分表(1. 目前京東到家還沒有到分庫的階段,2. 按門店維度進行分表數(shù)據(jù)量會相對均衡一些,所以沒有按照商家維度進行劃分)。

那么在商家 PC 端上查詢所有商品庫存及維護庫存時帶來了難度,比如查詢該商家下所有的商品有多少條,同時處于上架狀態(tài)的商品有哪些……,為了解決這一難題,引入了 ES,將數(shù)據(jù)統(tǒng)一存儲在 ES 集群中,解決一些涉及到聚合查詢的場景。

庫存系統(tǒng)數(shù)據(jù)流轉(zhuǎn)

庫存系統(tǒng)數(shù)據(jù)流轉(zhuǎn)圖

庫存系統(tǒng)數(shù)據(jù)流轉(zhuǎn)圖解釋說明:

庫存系統(tǒng)的數(shù)據(jù)流轉(zhuǎn),指的都是銷售庫存的數(shù)據(jù)流轉(zhuǎn),在京東到家還有自營類業(yè)務(wù)板塊,即上圖中提到的城市倉,由于它涉及到采購入庫及盤盈盤虧等問題, 所以會由一套 WMS 系統(tǒng)來支撐。

京東到家設(shè)計初衷就是希望商家下的商品各門店共享,帶來的問題就是商家新建一個商品時,需要推送到商家下所有的門店中,即所有的門店均可以看到這個商品。或者商家新建一個門店時,需要將商家下所有的商品均推送到這個新建的門店中,所以這采用了 MQ 技術(shù)進行異步化批量處理。

寫到這里,相信對大家對庫存系統(tǒng)有了初步的了解,從上圖來看功能上其實并不復(fù)雜,但是他面臨的技術(shù)復(fù)雜度卻是相當高的,比如秒殺品在高并發(fā)的情況下如何防止超賣。

另外庫存系統(tǒng)還不是一個純技術(shù)的系統(tǒng),需要結(jié)合用戶的行為特點來考慮,比如下文中提到什么時間進行庫存的扣減最合適,我們先拋出幾個問題和大家一起探討下,如有不妥之處,歡迎大家拍磚。

庫存什么時候進行預(yù)占 (或者扣減) 呢

商家銷售的商品數(shù)量是有限的,用戶下單后商品會被扣減,我們可以怎么實現(xiàn)呢?

舉個例子: 一件商品有 1000 個庫存,現(xiàn)在有 1000 個用戶,每個用戶計劃同時購買 1000 個。

  • 實現(xiàn)方案 1:如果用戶加入購物車時進行庫存預(yù)占,那么將只能有 1 個用戶將 1000 個商品加入購物車。

  • 實現(xiàn)方案 2:如果用戶提交訂單時進行庫存預(yù)占,那么將也只能有 1 個用戶將 1000 個商品提單成功,其它的人均提示“庫存不足,提單失敗”。

  • 實現(xiàn)方案 3:如果用戶提交訂單 & 支付成功時進行庫存預(yù)占,那么這 1000 個人都能生成訂單,但是只有 1 個人可以支付成功,其它的訂單均會被自動取消。

京東到家目前采用的是?方案 2,理由如下:

用戶可能只是暫時加入購物車,并不表示用戶最終會提單并支付。

所以在購物車進行庫存校驗并預(yù)占,會造成其它真正想買的用戶不能加入購物車的情況,但是之前加車的用戶一直不付款,最終損失的是公司。

方案 3 會造成生成 1000 個訂單,無論是在支付前校驗庫存還是在支付成功后再檢驗庫存,都會造成用戶準備好支付條件后卻會出現(xiàn) 99.9% 的系統(tǒng)取消訂單的概率,也就是說會給 99.9% 的用戶體驗到不爽的感覺。

數(shù)據(jù)表明用戶提交訂單不支付的占比是非常小的(相對于加入購物車不購買的行為),目前京東到家給用戶預(yù)留的最長支付時間是 30 分鐘,超過 30 分鐘訂單自動取消,預(yù)占的庫存自動釋放。

綜上所述,方案 2 也可能由于用戶下單預(yù)占庫存但最終未支付,造成庫存 30 分鐘后才能被其它用戶使用的情況,但是相較于方案 1,方案 3 無疑是折中的最好方案。

重復(fù)提交訂單的問題?

重復(fù)提交訂單造成的庫存重復(fù)扣減的后果是比較嚴重的。比如商家設(shè)置有 1000 件商品,而實際情況可能賣了 900 件就提示用戶無貨了,給商家造成無形的損失

可能出現(xiàn)重復(fù)提交訂單的情況:

  • 1、用戶善意行為:app 上用戶單擊“提交訂單”按鈕后由于后端接口沒有返回,用戶以為沒有操作成功會再次單擊“提交訂單”按鈕

  • 2、用戶惡意行為:黑客直接刷提單接口,繞過 App 端防重提交功能

  • 3、提單系統(tǒng)重試:比如提單系統(tǒng)為了提高系統(tǒng)的可用性,在第一次調(diào)用庫存系統(tǒng)扣減接口超時后會重試再次提交扣減請求

好了,既然問題根源縷清楚了,我們一一對癥下藥

  • 1、用戶善意行為:App 側(cè)在用戶第一次單擊“提交訂單”按鈕后對按鈕進行置灰,禁止再次提交訂單

  • 2、用戶惡意行為:采用令牌機制,用戶每次進入結(jié)算頁,提單系統(tǒng)會頒發(fā)一個令牌 ID(全局唯一),當用戶點擊“提交訂單”按鈕時發(fā)起的網(wǎng)絡(luò)請求中會帶上這個令牌 ID, 這個時候提單系統(tǒng)會優(yōu)先進行令牌 ID 驗證,令牌 ID 存在 & 令牌 ID 訪問次數(shù) =1 的話才會放行處理后續(xù)邏輯,否則直接返回

  • 3、提單系統(tǒng)重試:這種情況則需要后端系統(tǒng)(比如庫存系統(tǒng))來保證接口的冪等性,每次調(diào)用庫存系統(tǒng)時均帶上訂單號,庫存系統(tǒng)會基于訂單號增加一個分布式事務(wù)鎖。

偽代碼如下:

庫存數(shù)據(jù)的回滾機制如何做?

需要庫存回滾的場景也是比較多的,比如:

  • 1、用戶未支付:用戶下單后后悔了

  • 2、用戶支付后取消:用戶下單 & 支付后后悔了

  • 3、風控取消:風控識別到異常行為,強制取消訂單

  • 4、耦合系統(tǒng)故障:比如提交訂單時提單系統(tǒng) T1 同時會調(diào)用積分扣減系統(tǒng) X1、庫存扣減系統(tǒng) X2、優(yōu)惠券系統(tǒng) X3,假如 X1、X2 成功后,調(diào)用 X3 失敗,需要回滾用戶積分與商家?guī)齑妗?/p>

其中場景 1、2、3 比較類似,都會造成訂單取消,訂單中心取消后會發(fā)送 MQ 出來,各個系統(tǒng)保證自己能夠正確消費訂單取消 MQ 即可。

而場景 4 訂單其實尚未生成,相對來說要復(fù)雜些,如上面提到的,提單系統(tǒng) T1 需要主動發(fā)起庫存系統(tǒng) X2、優(yōu)惠券系統(tǒng) X3 的回滾請求(入?yún)⒈仨殠嫌唵翁?#xff09;,X2、X3 回滾接口需要支持冪等性。

其實針對場景 4,還存在一種極端情況,如果提單系統(tǒng) T1 準備回滾時自身也宕機了,那么庫存系統(tǒng) X2、優(yōu)惠券系統(tǒng) X3 就必須依靠自己來完成回滾操作了,也就是說具備自我數(shù)據(jù)健康檢查的能力,具體來說怎么實現(xiàn)呢?

可以利用當前訂單號所屬的訂單尚未生成的特點,可以通過 worker 機制,每次撈取 40 分鐘(這里的 40 一定要大于容忍用戶的支付時間)前的訂單,調(diào)用訂單中心查詢訂單的狀態(tài),確保不是已取消的,否則進行自我數(shù)據(jù)的回滾。

多人同時購買 1 件商品,如何安全地庫存扣減?

現(xiàn)實中同一件商品可能會出現(xiàn)多人同時購買的情況,我們可以如何做到并發(fā)安全呢?

偽代碼片段 1:

偽代碼片段 1 的設(shè)計思想是所有的請求過來之后首先加鎖,強制其串行化處理,可見其效率一定不高。

偽代碼片段 2:

這段代碼只是在 where 條件里增加了and stockNum>="+requestBuyNum即可防止超賣的行為,達到了與上述偽代碼 1 的功能。

如果商品是促銷品(比如參與了秒殺的商品)并發(fā)扣減的機率會更高,那么數(shù)據(jù)庫的壓力會更高,這個時候還可以怎么做呢?

海量的用戶秒殺請求,本質(zhì)上是一個排序,先到先得。但是如此之多的請求,注定了有些人是搶不到的,可以在進入上述偽代碼 Dao 層之前增加一個計數(shù)器進行控制,比如有 50% 的流量將直接告訴其搶購失敗,偽代碼如下:

另外同一個用戶,不允許多次搶購?fù)患唐?#xff0c;我們又該如何做呢?

如果同一個用戶擁有不同的帳號,來搶購?fù)患唐?#xff0c;上面的策略就失效了。一些公司在發(fā)展早期幾乎是沒有限制的,很容易就可以注冊很多個賬號。也即是網(wǎng)絡(luò)所謂的“僵尸賬號”,數(shù)量龐大,如果我們使用幾萬個“僵尸號”混進去搶購,這樣就可以大大提升我們中獎的概率,那我們?nèi)绾螒?yīng)對呢?

庫存系統(tǒng)的核心表結(jié)構(gòu)設(shè)計

下面列出了庫存系統(tǒng)的核心表結(jié)構(gòu),提供出來供大家在工作中能夠有所參考。

庫存主表,命名規(guī)則:stock_center_00~99 庫存主表

庫存流水表,命名規(guī)則:stock_center_flow_00~99 庫存流水表

庫存批量操作日志表,命名規(guī)則:batch_upload_log 庫存批量操作日志表

作者介紹

柳志崇,2008 年計算機專業(yè)畢業(yè),一直從事于移動互聯(lián)網(wǎng)及 O2O 新零售業(yè)務(wù)領(lǐng)域的工作,參與過京東到家多個億級 PV 系統(tǒng)的研發(fā)與架構(gòu),對高并發(fā)有著豐富的實戰(zhàn)經(jīng)驗。

本文是聊聊架構(gòu)社群分享的內(nèi)容。如果你也有好內(nèi)容,歡迎你也來社群分享。

Q&A

Q:

億級 PV 系統(tǒng)的架構(gòu)能否介紹下,怎么做到高并發(fā)的?

A:

高并發(fā)這個詞業(yè)內(nèi)外使用得很泛濫,因為并沒有一個統(tǒng)一的定義,比如 qps、tps 達到多少就是高并發(fā)了。

一個系統(tǒng)設(shè)計的早期更多地關(guān)注功能迭代,隨著平臺的發(fā)展,用戶、商家、商品數(shù)據(jù)的持續(xù)增長,直到有一天有人告訴你,說你的系統(tǒng)太慢了,或者程序處理上的數(shù)據(jù)不對時,表明你是時候該重視高并發(fā)了。

接下來我談?wù)勱P(guān)于庫存系統(tǒng)這塊高并發(fā)的思路,供參考。

  • 服務(wù)接口的無狀態(tài)化設(shè)計,方便隨時隨地可以水平擴容

  • 服務(wù)接口的冪等性設(shè)計,防止重復(fù)提交造成的重復(fù)扣減

  • 服務(wù)接口的限流與截流設(shè)計,應(yīng)對異常流量造成整個系統(tǒng)癱瘓

  • 針對讀多寫少的場景進行數(shù)據(jù)緩存,緩存時還應(yīng)該注意緩存擊穿的問題

  • 庫存數(shù)據(jù)持續(xù)增多時勢必會考慮數(shù)據(jù)庫分庫分表,分庫分表路由規(guī)則設(shè)計:1、一定要緊貼業(yè)務(wù),否則在一些聚合查詢上非常麻煩;2、避免短期內(nèi)出現(xiàn)二次擴容的可能性

關(guān)于庫存分庫或分表使用什么策略,京東到家接入的商家多半是優(yōu)質(zhì)商家,通常一個商家會有多個門店,目前庫存系統(tǒng)采用的門店維度進行分表:

1、目前的體量還沒有進行分庫;

2、分表路由算法是門店編號取模 + 大門店定向路由組合,來避免簡單的取模算法造成表數(shù)據(jù)分布可能出現(xiàn)的嚴重不平衡問題

Q:

為什么京東到家的庫存和京東商城的庫存要單獨的呢?

A:

京東商城與京東到家是兩款 App,兩款有著各自獨立的消費場景與目標人群,系統(tǒng)設(shè)計上是有些差異化的,如果我們從架構(gòu)的角度來說,他們之間是解耦的,帶來顯而易見的好處就是其中一個掛了不會影響到另外一個。

京東到家比京東商城起步晚了整整 12 年,所以設(shè)計之初是借鑒了京東商城的庫存系統(tǒng)的,但是京東到家中涵蓋的服務(wù)類商品 (比如上門美甲按摩庫存是具體的人,而一個人是不能同時被預(yù)約提供服務(wù)的)、外賣類商品 (庫存相對更加簡單,通常只有貨品充足、貨品緊張、無貨幾種狀態(tài)) 是京東商城中沒有的。

另外京東到家處于一個產(chǎn)品高速迭代期,可能一周就一個版本,由于與京東商城相互獨立,有問題了影響也可以控制到很小。

Q:

1、定時 40 分撈取,萬一 39 分那時候服務(wù)重啟了,錯過這個定時任務(wù)撈取,怎么辦?

2、同一局域網(wǎng)中,如果對外 IP 都是同一個,受到限制那怎么辦?

3、取模限制一部分流量搶購失敗,萬一流量在促銷庫存量之內(nèi),那是不是最多只能賣出一半?從取模看,也就是 userID 被模為 1 的用戶,總是搶不到了?

A:

1、這個問題很好,問得很仔細,這一塊就考驗定時任務(wù)的調(diào)度機制了,首先調(diào)度策略是每分鐘執(zhí)行,檢測前 40 分鐘到前 50 分鐘之間訂單

2、看 doBuy1 方法,這里其實提到了,當同一個公網(wǎng) IP 訪問請求量超過了預(yù)設(shè)閾值,就會增加一個驗證碼環(huán)節(jié)

3、京東到家 App 目前 DAU 過百萬了,取模機制造成的只能賣出一半這個問題還沒有遇到過,不過有這個擔心是好的,實際開發(fā)過程中可以設(shè)這個取模的值為動態(tài)放行流量即可;另外你提到的 userId 被模 1,這個問題是不存在的,因為我不是用 userId 來取模的,請重新讀 buy 方法。

Q:

請問一下在高峰期每秒以下這個表會有多少的 tps?“庫存主表,命名規(guī)則:stock_center_00~99”

A:

首先這個表是異步更新的,不會阻塞主流程,目前觀察 tps 可以達到 800

Q:

如果是異步的話,就會有可能出現(xiàn)查庫存和實際庫存有差異。你是先把庫存都放 redis 然后再用 mq 扣減嗎?或者還是有其它解決方案?

A:

對外提供的 curd 都是基于 redis 的,所以不會出現(xiàn)不一致的問題,mysql 異步更新只是為了數(shù)據(jù)的持久化。

Q:

異地多活,用戶維度單元化下庫存是怎么處理的?

A:

異地多活,目前我們做到了服務(wù)的擴機房部署,數(shù)據(jù)的擴機房準實時備份,還沒有進行用戶維度的單元化。我也沒有實戰(zhàn)過,不過我覺得異地多活,架構(gòu)設(shè)計有幾點需要關(guān)注:

  • 1、避免冷備,即如果一個機房不出意外,另外一個機房永遠就是一個 backup,對于大型互聯(lián)網(wǎng)公司這個成本是非常高的;

  • 2、機房同源策略,一個網(wǎng)絡(luò)請求可能涉及到幾個幾十個系統(tǒng)的協(xié)同,應(yīng)當將這部分處理控制到同一個機房處理;

  • 3、就近訪問策略,通過智能 DNS,路由到離用戶最近的機房機房。

轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/articles/10251560.html

總結(jié)

以上是生活随笔為你收集整理的库存系统难破题?京东到家来分享的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。