內容來源:2017年4月22日,貝法易集團技術部總監黃亮在「2017年MongoDB中文社區深圳用戶組大會」進行《MongoDB在跨境電商物流供應鏈系統中的實踐》演講分享。IT 大咖說做爲獨家視頻合做方,經主辦方和講者審閱受權發佈。數據庫
閱讀字數:2896 | 4分鐘閱讀express
本次介紹下出口易跨境電商物流供應鏈系統從單體應用過渡到面向服務的分佈式系統架構的過程當中,遇到的一些挑戰和實現。其中包括了基於MongoDB建模和數據持久化方面上具體實踐。後端
出口易物流是廣州市貝法易商貿有限公司(簡稱貝法易)旗下,以全球倉儲爲核心,整合全球物流網絡系統,爲跨境電商賣家提供海外倉儲、國際專線、國際小包、國際快遞、FBA頭程等物流服務以及本地化售前售後服務,解決訂單管理、金融融資難題。咱們不是物流的供應商,咱們是跨境電商全程物流解決方案提供商。數組
咱們公司的重資產是人員,咱們瞭解跨境電商物流,包括跨境電商通關的環節、關於物流方面的國際法律以及離境品的相關信息,這些都是咱們公司最寶貴的資源。網絡
咱們公司底下有一大羣長期合做的供應商,這是咱們最大的優點。咱們的難點也是在於這些供應商是不可控的,由於咱們是在使用別人家的服務。架構
因此除了訂單系統還有一個很重要的資產就是咱們自營的海外倉儲,這也是咱們最核心的價值。併發
上圖是咱們全球佈局的物流網絡。這些倉儲有大有小,英國倉庫是咱們最核心的倉庫。截至2017年,在國內咱們一共有八個倉儲中心,重點的是在深圳、廣州和上海。框架
咱們合做的平臺推薦咱們的物流服務提供商有Amazon、ebay、wish、阿里國際、shopee、AliExpress還有LAZADA。分佈式
咱們以前的系統是上圖左邊的架構,針對商家第三方的ERP和一些商家本身研發的一套系統,還有一些平臺跟咱們的系統都是有直接交互。有的是經過出口易提供了一套UI來進行訪問,還有就是大量的線上發貨,咱們會採用API來進行接入。咱們後臺有admin管理後臺,還有單獨的一塊WMS系統。高併發
咱們認爲這個系統有些過於龐大,想作一些調整。新的架構大部分仍是沒有改動,只是在後端針對admin的系統想要往面向服務架構方向落地。基於業務場景的切分有兩塊,一塊是基於通用服務,好比說用戶的認證和受權,還有就是日誌。
支付有一些支付網關,有和paypal、alipay、payoneer還有銀行的接口。
下面是咱們業務最主要模塊,包括產品報價、客戶關係管理系統,還有訂單、物流網絡和運輸,包括WMS、支付、物流軌跡跟蹤、供應商管理系統,還有結算報表等等諸如此類。
單體應用:先後端系統共用一套WEB App Solution。
單一數據庫:採用MS SQLServer 數據庫,核心業務功能共用一個數據庫。
業務功能完整:IT系統隨業務的發展不斷擴展新功能。知足開展跨境電商物流業務最基本的功能性需求。
容易測試和部署:單獨一個Solution,系統依賴少,一旦部署,所有功能便可測試。
不夠靈活:對應用程序作任何細微的修改都須要將整個應用程序從新構建、從新部署。
妨礙持續交付:系統規模大,構建和部署時間也相應地比較長,不利於頻繁部署,阻礙持續交付。
受技術棧限制:包括開發語言,開發工具,數據庫一旦選定,沒法根據實際須要做其餘選擇。
技術負債:系統邏輯異常複雜,隨着時間推移,人員更迭,技術負債不斷累積。
面向服務:根據業務模塊切分不一樣的系統模塊,系統模塊採用面向服務架構。服務與服務經過明確的接口定義進行通信。
領域驅動設計:每一個業務模塊團隊負責一個領域或業務功能相關的所有開發。核心領域根據DDD中明肯定義的規則實現。
獨立部署、升級、擴展和替換:每一個服務能夠單獨部署,透明升級,不影響整個系統。
異構/採用多種語言:每一個服務開發團隊,能夠選擇本身熟悉開發語言,數據庫,開發工具和開發架構。
身份認證:每一個服務都須要統一的登陸認證。
鑑權:不一樣的用戶使用相同的服務模塊都須要鑑權。
由單點登陸的頁面包括基於OAuth2 API這樣的方式來接入。內部採用的是DDD這樣的一個邏輯架構,包括應用層、領域層。領域層裏面又包括了領域模型、實體子對象、領域服務、領域事件和查詢的規格。
基於倉儲,要存一個訂單,必須鏈接實體和子對象一塊兒存儲刷新到數據庫。
咱們作應用的時候更偏向於完成業務,因此選用了mangoDB。咱們有一套本身的架構,在封裝的過程當中就會把mangoDB作一層封裝。
上圖中面向切面的架構包括了exertion、loading和cache等切面。
上圖是TMS系統調撥單聚合根示意圖,它包括了物流軌跡的集合、預計到貨時間等信息,還有這些調撥單歷經的節點信息。
一、非事務緊密型。錯誤數據容忍性相對比較高。
二、團隊成員有使用MongoDB開發經驗。對基於MongoDB方面的建模須要考慮的必要冗餘有必定的瞭解。
三、Portal 模塊數據庫讀大於寫,基於MongoDB讀寫方面的高性能,解決了高併發下系統卡頓問題。
四、TMS 系統模型之間關係複雜,採用傳統關係數據庫,勢必增長一堆表。採用MongoDB,能夠把複雜的模型,經過一個Doucment存儲到一塊兒。
集合之間不能Join,建模方面要特別注意。建議增長必要的冗餘,減小二次查詢。
僅僅支持單個Document級別事務。數據一致性錯誤時,要考慮增長必要數據監控和數據修復功能。
聚合查詢,須要經過MongoDB 聚合管道方式查詢,MongoDB C# 驅動提供了良好支持,可是相對Linq查詢仍是比較繁瑣。
倉儲限定在對整個聚合根的操做上,提供聚合根的持久化和重建或查詢。
負責事務處理。每一個聚合根的倉儲都會關聯到同一個倉庫上下文。可是MongoDB 不支持事務,咱們提供了虛擬實現。倉儲上下文應用了工做單元模式。
簡單的CLR對象(簡單的Java對象),不繼承任何持久化框架中的基類,或實現任何持久化框架中的接口。領域層不引用MongoDB類庫。MongoDB倉庫層使用lambda expression 實現類的Map。
有多種ID生成器可供選擇。GuidGenerator,OjbectIdGenerator,String OjbectIdGenerator,etc。咱們ID一概使用String類型。因此直接使用MongoDB的StringObjectIdGenerator。
若是把多態類(繼承)映射到MongoDB,須要指定已知類型。
NamedIdMemberConvention能夠指定類的哪些屬性能夠做爲ID。
IgnoreExtraElementsConvention能夠忽略Document中不存在於類中的字段,不然會拋出異常。
EnumRepresentationConvention能夠指定枚舉序列化的方式,咱們都指定爲BsonType.String。
MongoDB2.2版本引入了此功能,是數據聚合的一個新框架。
這個框架一是對文檔進行「過濾」,也就是篩選出符合條件的文檔;二是對文檔進行「變換」,也就是改變文檔的輸出形式。其餘的也包括按照某個指定字段分組和排序等。
它實際上是MapReduce的替代方案,但比MapReduce簡單。
該框架使用聲明性管道符號來支持相似SQL 中的Group by 操做的功能。不須要本身編寫自定義的JavaScript。
$project:數據投影,主要用於重命名、增長和刪除字段。
$match:過濾操做,篩選符合條件文檔,做爲下一階段的輸入。
$limit:限制通過管道的文檔數量。
$skip:從待操做集合開始的位置跳過文檔的數目。
$unwind:將數組元素拆分爲獨立字段。
$group:對數據進行分組。
$sort:對文檔按照指定字段排序。
$geoNear:會返回一些座標值,這些值以按照距離指定點距離由近到遠進行排序。這個在地理信息系統中比較經常使用。
對於大多數的聚合操做,聚合管道能夠提供很好的性能和一致的接口。
使用起來比較簡單,和MapReduce同樣,它也能夠做用於分片集合。
輸出的結果只能保留在一個文檔中,要遵照BSON Document大小限制(當前是16M)。
管道對數據的類型和結果的大小會有一些限制,對於一些簡單的固定的。
彙集操做可使用管道,可是對於一些複雜的、大量數據集的聚合任務仍是使用MapReduce。
今天的分享就到這裏,謝謝你們!