天天看點

分布式商城項目09-海量訂單處理實戰

作者:認真覺醒者

1 背景

在電商系統中,說到海量的話,我們會有兩個反應,一個是海量的流量,另一個就是海量的訂單。關于海量的流量這個我們在講雙網關設計的時候已經講過了,但是對于秒殺的的流量處理,我們後面會有一個專門的子產品去講解。今天我們就講下如何處理海量的訂單。

訂單我們一般會存儲在關系型資料庫中,對于大型的電商公司可能會使用Oracle資料庫,在處理海量訂單的時候可能沒有這麼棘手。還有就是最近比較流行NewSql 資料庫,能夠提供可伸縮性、可用性和高性能,同時保持傳統資料庫使用Sql的習慣,可以處理海量的資料問題。

今天我們就傳統的Mysql資料庫如何處理海量訂單,從技術的層面進行實戰分析。

2 規劃

對于海量的資料,對于我們電商系統的直接影響就是查詢慢。我們的方案的思路也就是減少查詢表的資料量,那我們怎麼做呢,那就是分庫分表的思路,到底是分庫還是分表,需要我們清楚的認識到一個問題,拆的越分散,并發和維護就很麻煩,系統出問題的機率會很高,定位排查問題會非常的難受和麻煩。是以我們需要明白什麼情況下需要分庫,什麼情況下需要分表。

這個思路其實也不是很難,我們都知道資料庫是有連接配接數限制的,如果并發高的情況下,分庫是最優的選擇。尤其是在分布式微服務的架構中,前期我們會根據業務進行分庫處理,這樣一方面可以獨立開發,另一方面減少但資料庫的壓力,這個大家一般都這麼做,可能也沒想這麼多吧。對于單表資料量比較的大的,則适合分表,比如1TB的資料,如果分成100張表,每張表也就10G的資料,每條訂單1KB的話,也就1000w的資料量,這樣查尋毫無壓力啊。是以我們的任務就是到底要拆多少張表的問題,如何去分表的問題。

我們都知道,Mysql 使用的是B+樹的結構,對于三層的B+樹,大約可以存儲2000w條的資料(這個資料可以大約計算出來),加入我們做一個中型的電商系統,每天100w的訂單量,一個越大約3000w,一年3.6億條資料,我們按4億算。我們拆表的數量一定要是2的幂,如果是4億資料,需要拆成20張表,最終我們會分成32張表。同時,我們也有個訂單的明細表,這個跟訂單表是一對一的關系,有的地方會設計父子訂單的結構,父訂單的量會少一些,子訂單的量跟我的估計差不多,也可以根據這個思路去拆分。

到這,大家會想到一個問題,你這個系統隻是規劃了一年,難道我這個系統隻能運作一年嗎?先别急,這個就是我接下來說的問題,曆史資料的歸檔,我們一般保留半年,甚至三個月的的資料在訂單的資料庫,其他的資料我們會歸檔到曆史表中,如果查詢之前的訂單就需要去曆史庫中查詢,是以,我們系統正常運作的查詢量都是在我們的規劃範圍内的。

3 分表技術選型

分表的技術其實選擇的技術比較有限,主要的有以下幾種:

  • 手動分庫分表:就是定義多個資料源,在代碼層面指定通路的資料源。
  • 元件的方式:目前常用的是 Sharding-JDBC,可以內建到項目中,自動的路由到對應的資料庫上。
  • 代理方式:就是對資料庫進行代理,然後路由到對應的資料庫,目前像Mycat,Sharding-proxy應用的比較多。

對于上述的三種方式,我們推薦的是第二種,這種方式代碼侵入小,能兼顧性能和穩定性,也是我們今天實戰的重點。如果系統比較小的話,可以考慮第一種手工的方式。第三種方式我們不推薦,如果系統非常龐大的話,可以考慮,畢竟中間加了一層代理,系統的不穩定因素就會增加,但是對應用程式來說是完全透明的。

4 分庫分表實戰

我們要進行分表的話,需要選擇一個合适的片鍵和分片的算法,這個直接影響分庫分表的效果。訂單中訂單号是具有唯一性,我們可以根據訂單号做為片鍵,對于電商系統,我們有時候會按照訂單号進行查詢,同時也會根據使用者的id去查詢,是以需要我們生成訂單号的時候,需要把訂單号和使用者的userId 結合起來,這樣查詢的時候就不會跨庫或跨表。

  • 分庫分表實戰

首先引入sharding-jdbc的jar包

分布式商城項目09-海量訂單處理實戰

同時配置sharding-jdbc的資料源和分片算法

分布式商城項目09-海量訂單處理實戰

分片算法

分布式商城項目09-海量訂單處理實戰

這樣我們就完成了分表分表的操作。

  • 曆史資料歸檔實戰
分布式商城項目09-海量訂單處理實戰

我們建立兩個訂單的服務,一個曆史歸檔資料查詢的,一個是對訂單資料入庫查詢的。同時還有一個訂單歸檔的定時任務程式。

5 總結

其實我們使用分庫分表後,就會極大的限制資料庫的查詢能力,有些很簡單的關聯查詢,分庫分表後可能就沒法實作了,當資料量或者流量達到海量的情況下,我們才會使用這個方式吧,真的是有點壯士斷腕的感覺。

繼續閱讀