解密京東千億商品系統核心架構

来源:https://www.cnblogs.com/mylanqiu/archive/2018/10/10/9764841.html
-Advertisement-
Play Games

商品,黃金交易流程最基礎、最核心的環節,無商品不電商。商品數據無處不在,商家(採銷、供應商)發佈管理、供應商下採購單、倉儲配送、促銷、搜索、商詳頁展現、購物支付、財務結算、售後服務等,都離不開商品。商品信息要準確傳導於京東整個供應鏈的各節點,必須要有一套穩健、可靠的商品服務體系支撐。 原本並沒有統一 ...


商品,黃金交易流程最基礎、最核心的環節,無商品不電商。商品數據無處不在,商家(採銷、供應商)發佈管理、供應商下採購單、倉儲配送、促銷、搜索、商詳頁展現、購物支付、財務結算、售後服務等,都離不開商品。商品信息要準確傳導於京東整個供應鏈的各節點,必須要有一套穩健、可靠的商品服務體系支撐。

原本並沒有統一的商品服務及存儲。DBA搭建了一套包含若幹層級的SqlServer資料庫複製結構,各系統從各級從庫讀取數據。複製延遲嚴重的時候,超過12小時,從庫還沒有更新,嚴重影響用戶體驗。寫入口不止一個,獲取到寫賬號就可以寫入。erp商品管理系統、POP商品系統、BIP甚至也開發了一個商品管理系統,都在寫同一個庫的同一套表,數據一致性無法得到保障。在那個階段京東的訂單量、用戶量相對較少,基於資料庫的架構一定程度上也能支撐日常流量,但是無法應對大型促銷活動。

在此背景下,2012年3月商品組從網站組獨立出來,孫歌臨危受命組建團隊,啟動商品技術架構升級項目。京東618年中狂歡購物節,系統(特別是0點)會承受平時無法比擬的壓力。2012年之前的大促都會出現系統問題系統經常出現問題,甚至圖書搶購活動時直接系統宕機。基於資料庫提供讀服務的架構,顯然已經無法支撐業務前行,升級改造勢在必行。12年初NoSQL還是新鮮事物,交易架構師龔傑開始實踐Redis,他在一封郵件中介紹自主封裝的客戶端以及API。商品團隊開始基於redis記憶體資料庫搭建商品讀服務,並對開源Jedis做了深度封裝,擴展了ShardedJedisPool,實現了更加細粒度的多分片連接池管理,並且將一個請求中命中到同一個分片的redis命令由串列改成pipeline並行執行,性能提升較大。

架構1.0 讀服務化

由Redis存儲全量商品數據,作為記憶體資料庫使用。商品信息變動時增量更新,一主多備模式容災,同時全量刷新程式作為最後保障,一旦Redis中數據全部丟失,可以將商品庫中數據恢復到Redis。

交易系統直面用戶,為保證用戶選品、下單結算的順暢,提升用戶體驗。交易系統對高性能、高可用的商品讀服務需求最迫切。此時架構升級採取了一種“輕模式”,所謂輕是指儘量減少外部系統的改造,這樣更利於工作的快速推進。首先在通知模式上,各種商品系統寫入Sqlserver主庫後,通過HttpHTTP服務通知Rcat -server(採取儘量做的策略,能通知就通知到,有異常也不去重試,這種策略對相關係統的改造最小)。Rcat-server的職責就是接收通知,之後查詢主庫中的商品信息,將其更新到Redis中。因為寫入系統是儘量做,不保證成功的模式,因此需要補償機制去彌補遺漏。非同步Worker會定期掃描資料庫,把當日更新的,從刷新到Redis中。

V1.0版架構非常不完美,只是讀服務這個點進行了改造,但是卻在當年618中完美的完成了任務。618當天像往年一樣,研發工程師售後守候在運維同學周圍,時刻準備著!整個過程波瀾不驚,只有過個別應用過載重啟,整體非常順利扛過了大流量的考驗。有了這個經驗,研發工程師們開始將Rcat(應用名稱,商品讀服務)推廣,依賴Sqlserver從庫的系統都逐步切換到讀服務上。

架構2.0 全面服務化

POP商品系統和自營商品系統都是寫入Oracle,在通過非同步worker將數據寫會Sqlserver。京東商品的獨特之處在於最初是自採自銷的自營類商品,有自己的商品模型和對應的erp管理系統。後續有了POP開放平臺,該平臺的商品模型和系統是獨立搭建的,適應於第三方商家的商品發佈管理。而所有下游的系統(單品、搜索、訂單生產、倉庫等)都是基於最初Sqlserver自營skuSKU模型做的系統設計。所以POP商品有自己的Oracle存儲,也必須京東經過一步非同步程式轉化,寫到Sqlserver商品庫中。而自營商品系統在2011年架構升級時,計劃由.Net+Sqlserver的技術體系升級外Java+Oracle技術體系。

孫歌作為研發負責人,基於技術前瞻性和成本考慮,果斷決策放棄既昂貴又沒有DBA團隊良好支持的Oracle資料庫。轉而直接基於SqlServer實現商品的全面服務化,相比其他系統的去O足足早了一年。當時的整體思路是先實現服務化,再進行存儲升級(Mysql集群),最終完成徹底的技術架構升級。全面服務化過程:

1). 全面讀服務體系:
將下游系統讀取的信息刷新到Redis中,由讀服務Rcat統一支持根據skuId查詢的需求。對於檢索需求,例如根據分類id查詢SkuSKU列表,搭建Solr索引服務。基於各系統的需求收集已經當前SQL的分析,搭建了讀服務體系,並逐步推廣,去掉各系統對Sqlserver資料庫的讀取依賴。

2).寫服務化
接管所有商品寫操作,提供商品相關的基本讀寫服務,建立商品主數據中心,服務於自營商品管理、POP平臺、圖書音像商品管理等系統。京東起家於3C自營產品, SKU化管理。後發展的POP平臺,是商品化發佈管理。寫服務必須相容兩套模型,平滑過渡。研發工程師最終設計為統一到商品-skuSKU模型,自營商品與SkuSKU一對一,而POP商品與SkuSKU是一對多。自營商品每發佈一個商品有且僅有一個SKUSku,pop商家發佈一個商品可以有多個SkuSKU。自營商品溝通通過後期的顏色尺碼綁定,實現銷售關係捆綁。這樣展現給用戶的效果是一樣的,同時對於京東採銷、POP商家都可以按各自的習慣去操作商品。

寫服務設計時架構師尤鳳凱充分考慮了擴展性、可復用性,實現了模塊可配置化。基於商品介紹、擴展屬性、規格參數、特殊屬性等基礎組件,可靈活組配不同的業務流程。使用了京東自主研發的SAF中間件,其支持負載均衡、自動故障切換、流量控制、黑白名單等特性,並且在性能方面表現優異。

3).去O:去掉自營商品系統的Oracle,直接寫Sqlserver降低延遲,縮短商家發佈到展現給最終用戶的時間。
4).非同步引擎:建立下發服務系統,統一化消息通知網站、WMS等下游系統。

最初的商品變動時,只需要通知WMS系統, 因為採購入庫時,倉庫需要核實商品信息。隨著整個京東服務化進程的推進,搜索、單品頁等系統都希望得到通知。因此規划了下發服務,在商品信息變動後,非同步通知這些系統。將商品信息入庫後,同步寫”操作日誌”到Redis隊列,再由worker非同步從Redis中取日誌,拿到變動變更的skuSKU,組裝信息化發MQ消息出去。此時的消息採取通用化設計,例如基本信息MQ、特殊屬性MQ等。

5).存儲升級:商品主數據存儲由Sqlserver單庫,升級為MySQL集群,併進行垂直、水平劃分, 分庫解決單庫吞吐量瓶頸,分表控制單表數據量。自主研發數據中間件,可以實現主庫的路由、從庫的負載均衡、故障的切換等,統一負責數據訪問,使得底層存儲規則對應用層透明。結合當前數據總量及增長率,預計3年後達到的數據量,做存儲容量規劃,並且做了Pre-Sharding方式,方便後續擴容。對於非片鍵外的查詢,使用二級路由或者搜索服務來解決。

隨著商品及SKU數量顯著增長、TPS逐步走高。寫服務、下發服務耦合的弊端越來越突出顯現。如1-2圖中紅色線條形成的環狀所示,寫服務和下發服務是相互影響的。假設寫Redis變慢,會影響整體寫入性能;如果DB遇到瓶頸,反過來又回會影響到下發服務,回查DB變慢,下發服務處理變慢。因此寫服務經常會出現抖動,寫變慢、下發延遲。

架構3.0平臺化、精準化

2015年中開始,架構師李帥啟動3.0架構升級,其理念是解耦、簡化。架構越簡單越好,沒接觸過的人新人很快可以上手;架構也必須松耦合的,寫、下發、讀都可以各自做升級,相互不影響,逐步提升整體性能。

用Jingobus基於從庫日誌識別商品信息變動,併發送通知、刷新redis集群。非同步引擎消息可配置化,商品屬性的組合對應消息隊列。例如:搜索關註skuSKU狀態變化,那麼只有skuSKU的上下櫃狀態變化時,才會發送消息,消息體中只包含skuSKU編號及狀態。可配置化的任務引擎,新需求響應快、開發接近零成本;實現了按需發送,給消費方減壓(例如:給wms的消息量降低80%+);並且寫系統解耦,整體穩定性增強。在推廣過程中,還進行跨部門技術協作,共同升級技術架構。例如網站單品頁數據異構升級項目,降低50%+介面交互,節約上百台Docker。

商品服務作為超0級系統 ,必須具有高可用性。任何影響到訂單的系統故障都必須在三分鐘內解決,有了統一切換平臺,執行預案是可以很快的。因此發現問題並警報至關重要。在研發負責人趙湘建的引領下,商品組啟動秒級監控平臺的研發。記憶體級監控信息收集、合併、延遲秒級。並且實現了秒級監控的平臺化,可將監控能力輸出到其他系統。

期間商品讀服務也在持續進行著升級。因為skuSKU數量大(數十億)且持續增長(周增長率約105%),Redis存儲集群規模也大。讀服務為其他眾多系統提供商品數據的查詢服務,訪問量很大,特別是在618,雙11期間,所以需要多組Redis集群分擔流量。NIO的Redis客戶端,降低了連接數量;後續為解決多組Redis集群流量均衡問題,對NIO版本的客戶端做了擴展,實現了多分片連接統一管理,使其負載均衡,並能當某一分片宕機的情況下,自動從集群中剔除,恢復後自動加入集群中,達到故障自動轉移與恢復的目的。不僅提高了集群整體的吞吐量,而且提升了可靠性。

同時因為商品數量增長很快,Redis集群的規模也成倍增加,為減少資源的利用,設計三級緩存功能,將最熱數據放應用記憶體中,緩存時間較短;熱數據放在規模較小的Redis集群中,全量數據放到規模較大的集群中,這樣全量數據的Redis集群OPS較少,可以減少部署組數,從而減少資源利用。

圖1-3 商品架構V3.0

京東商品系統在業務創新、數據智能化、性能及穩定性提升方面,將持續努力提升,努力實踐讓技術改變生活的願景。

本文轉載自:http://www.dalbll.com/Group/Topic/ArchitecturedDesign/5121


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、變數作用域 變數作用域指的是變數的作用範圍,javascript中的變數分為全局變數和局部變數 1、全局變數:在函數之外定義的變數,為整個頁面公用,函數的內部外部都可以訪問。 2、局部變數:在函數內部定義的變數,只能在定義該變數的函數內部訪問,外部無法訪問。函數內部訪問變數時,先在內部查找是否有 ...
  • 在前面,我們學習了標準文檔流,但在實際製作的過程中,用標準文檔流書寫顯然是不現實的,因此,我們來瞭解幾種脫離標準文檔流的方法: 1.float 浮動 float:left/right;(左浮/右浮) 效果:元素都加浮動,後面的元素緊跟前面的元素併排排列 第一個加了float,脫離了標準文檔流,對於瀏 ...
  • 安裝 新建一個文件夾 i18n ,內新建 en.js zh.js index.js 三個文件 準備翻譯信息 en.js zh.js index.js 創建Vue-i18n實例 i18n 掛載到 vue 根實例 main.js 簡單的使用 about.vue 註意: 比如說上面的hi 你要通過這種形式 ...
  • 在h5中實現一些小標簽、按鈕的時候,很容易發現部分安卓機型上的字體顯示有問題,總會向上偏移2px左右。這是設置padding或line-height無法修複的,與rem也無關,即使在字體大於12px時依然存在。下圖來自於網友的分享,從左到右依次是顯示正常的蘋果、顯示正常的安卓、顯示異常的安卓: 可能 ...
  • IndexedDB 瀏覽器資料庫,是一個非關係型資料庫,數據形式使用的是json,IndexedDB適合存儲大量數據,它的API是非同步調用的,當然他的api 也相對複雜。 當然瀏覽器數據存儲 還有LocalStorage,Cookies,web SQL等 為什麼還再來一個indexedDB。 之前我 ...
  • var date = new Date(); //Sat Sep 29 2018 10:44:43 GMT+0800 (中國標準時間) ]new Date().toLocaleString(); // 可根據本地時間把 Date 對象轉換為字元串,並返回結果。 "2018/9/29 上午10:45: ...
  • 這篇文章本來是想模塊導入導出和事件迴圈一起寫的,但是感覺一起寫的話會太長了,所以就分開兩篇文章寫吧。下一篇會重點介紹一下js中的事件迴圈,js代碼到底是以何種順序去執行的呢?我相信你看懂了事件迴圈再去看node對你的幫助是非常大的。 講模塊系統之前先認識一下node.js中的全局對象。 node.j ...
  • 教程所示圖片使用的是 github 倉庫圖片,網速過慢的朋友請移步 "《webpack4 系列教程(十二):處理第三方 JavaScript 庫》原文地址" 。或者來我的小站看更多內容: "godbmw.com" 0. 課程介紹和資料 " 本節課源碼" " 所有課程源碼" 本節課的代碼目錄如下: 本 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...