唯品會架構師是如何實現架構重構的

架構師springboot發表於2018-11-25

隨著唯品會業務的快速發展,訂單量的不斷增長,原有的訂單儲存架構已經不能滿足公司的發展了,特別是在大促高峰期,原訂單庫已經成為搶購瓶頸,已經嚴重製約公司的發展。

唯品會舊訂單庫包含幾十張訂單相關表,舊訂單庫是典型的一主多從架構;主庫容量已接近伺服器物理空間上限,同時也已經達到 MySQL 的處理上限,很快將無法再處理新增訂單。

舊訂單庫面臨的問題有:

1、超大容量問題

訂單相關表都已經是超大表,最大表的資料量已經是幾十億,資料庫處理能力已經到了極限;

單庫包含多個超大表,佔用的硬碟空間已經接近了伺服器的硬碟極限,很快將無空間可用;

2、效能問題

單一伺服器處理能力是有限的,單一訂單庫的 TPS 也有上限,不管如何優化,總會有達到上限,這限制了單位時間的訂單處理能力,這個問題在大促時更加明顯,如果不重構,訂單達到一定量以後,就無法再繼續增長,嚴重影響到使用者體驗。

3、升級擴充套件問題

單一主庫無法靈活的進行升級和擴充套件,無法滿足公司快速發展要求;

所有的訂單資料都放在同一庫裡面,存在單點故障的風險;

綜上所述,容量、效能問題是急需解決的問題,擴充套件是為了將來 3~5 年內能夠很好的滿足唯品會快速發展的需要,而不需要每隔幾個月花費人力物力去考慮擴容等問題。

解決方法思考

1、解決容量問題

我們可以考慮到最直接的方式是增加大容量硬碟,或者對 IO 有更高要求,還可以考慮增加 SSD 硬碟來解決容量的問題。此方法無法解決單表資料量問題。

可以對資料表歷史資料進行歸檔,但也需要頻繁進行歸檔操作,而且不能解決效能問題。

2、解決效能問題

提高資料庫伺服器的配置,這個可以提升一定數量的 QPS 和 TPS,但仍然不能解決單伺服器連線數、IO 讀寫存在上限的問題,此方法仍然存在單點故障的問題。

拆分方法探討

常見的資料庫拆分方式有三種:垂直拆分、水平拆分、垂直水平拆分。

1、垂直拆分

垂直拆庫是根據資料庫裡面的資料表的相關性進行拆分,比如:一個資料庫裡面既存在使用者資料,又存在訂單資料,那麼垂直拆分可以把使用者資料放到使用者庫、把訂單資料放到訂單庫。如下圖:

唯品會架構師是如何實現架構重構的
垂直拆表是對資料表進行垂直拆分的一種方式,常見的是把一個多欄位的大表按常用欄位和非常用欄位進行拆分,每個表裡面的資料記錄數一般情況下是相同的,只是欄位不一樣,使用主鍵關聯,如下圖:

唯品會架構師是如何實現架構重構的
2、水平拆分

水平拆分是把單表按某個規則把資料分散到多個表的拆分方式,比如:把單表 1 億資料按某個規則拆分,分別儲存到 10 個相同結果的表,每個表的資料是 1 千萬,拆分出來的表,可以分別放至到不同資料庫中,即同時進行水平拆庫操作,如下圖:

唯品會架構師是如何實現架構重構的

水平拆分可以降低單表資料量,讓每個單表的資料量保持在一定範圍內,從而提升單表讀寫效能。但水平拆分後,同一業務資料分佈在不同的表或庫中,可能需要把單表事務改成跨表事務,需要轉變資料統計方式等。

3、垂直水平拆分

垂直水平拆分,是綜合了垂直和水平拆分方式的一種混合方式,垂直拆分把不同型別的資料儲存到不同庫中,再結合水平拆分,使單表資料量保持在合理範圍內,提升總 TPS,提升效能,如下圖:

唯品會架構師是如何實現架構重構的
垂直拆分策略

原訂單庫把所有訂單相關的資料(訂單銷售、訂單售後、訂單任務處理等資料)都放在同一資料庫中,不符合電商系統分層設計,對於訂單銷售資料,效能第一,需要能夠在大促高峰承受每分鐘幾萬到幾十萬訂單的壓力;而售後資料,是在訂單生成以後,用於訂單物流、訂單客服等,效能壓力不明顯,只要保證資料的及時性即可;所以根據這種情況,把原訂單庫進行垂直拆分,拆分成訂單售後資料、訂單銷售資料、其他資料等,如下圖:

唯品會架構師是如何實現架構重構的

水平拆分策略

垂直拆分從業務上把訂單下單資料與下單後處理資料分開,但對於訂單銷售資料,由於資料量仍然巨大,最大的訂單銷售相關表達到幾十億的資料量,如果遇到大型促銷(如:店慶 128、419、618、雙十一等等),資料庫 TPS 達到上限,單銷售庫單訂單表仍然無法滿足需求,還需要進一步進行拆分,在這裡使用水平拆分策略。

訂單分表是首先考慮的,分表的目標是保證每個資料表的數量保持在 1000~5000 萬左右,在這個量級下,資料表的大小與效能是最理想的。

如果幾十個分表都放到一個訂單庫裡面,執行於單組伺服器上,則受限於單組伺服器的處理能力,資料庫的 TPS 有限,所以需要考慮分庫,把分表放到分庫裡面,減輕單庫的壓力,增加總的訂單 TPS。

1、使用者編號 HASH 切分

使用使用者編號雜湊取模,根據資料量評估,把單庫拆分成 n 個庫,n 個庫分別存放到 m 組伺服器中,如下圖:

need-to-insert-img

唯品會架構師是如何實現架構重構的

每組伺服器容納 4 個庫,如果將來單伺服器達到效能、容量等瓶頸,可以直接把資料庫水平擴充套件為 2 倍伺服器叢集,還可以繼續擴充套件為 4 倍伺服器叢集。水平擴充套件可以支撐公司在未來 3~5 年的快速訂單增長。

使用使用者編號進行 sharding,可以使得建立訂單的處理更簡單,不需要進行跨庫的事務處理,提高下單的效能與成功率。

2、訂單號索引表

根據使用者編號進行雜湊分庫分表,可以滿足建立訂單和通過使用者編號維度進行查詢操作的需求,但是根據統計,按訂單號進行查詢的佔比達到 80% 以上,所以需要解決通過訂單號進行訂單的 CURD 等操作,所以需要建立訂單號索引表。

訂單號索引表是用於使用者編號與訂單號的對應關係表,根據訂單號進行雜湊取模,放到分庫裡面。根據訂單號進行查詢時,先查出訂單號對應的使用者編號,再根據使用者編號取模查詢去對應的庫查詢訂單資料。

訂單號與使用者編號的關係在建立訂單後是不會更改的,為了進一步提高效能,引入快取,把訂單號與使用者編號的關係存放到快取裡面,減少查表操作,提升效能,索引不命中時再去查表,並把查詢結果更新到快取中。

3、分散式資料庫叢集

訂單水平分庫分表以後,通過使用者編號,訂單號的查詢可以通過上面的方法快速定位到訂單資料,但對於其他條件的查詢、統計操作,無法簡單做到,所以引入分散式資料庫中介軟體。

下圖是基本構架:

唯品會架構師是如何實現架構重構的

總結與思考

針對上面的技術我特意整理了一下,有很多技術不是靠幾句話能講清楚,所以乾脆找朋友錄製了一些視訊,很多問題其實答案很簡單,但是背後的思考和邏輯不簡單,要做到知其然還要知其所以然。如果想學習Java工程化、高效能及分散式、深入淺出。微服務、Spring,MyBatis,Netty原始碼分析的朋友可以加我的Java進階群:855801563,群裡有阿里大牛直播講解技術,以及Java大型網際網路技術的視訊免費分享給大家。

1.具有1-5工作經驗的,面對目前流行的技術不知從何下手,需要突破技術瓶頸的可以加群。

2.在公司待久了,過得很安逸,但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的可以加群。

3.如果沒有工作經驗,但基礎非常紮實,對java工作機制,常用設計思想,常用java開發框架掌握熟練的可以加群。

技術架構與業務場景息息相關,不能脫離實際的業務場景、歷史架構、團隊能力、資料體量等等去做架構重構,對於一家快速發展的電子商務公司,訂單系統是核心,訂單庫是核心的核心,訂單庫的重構就像汽車在高速公路上跑著的過程中更換輪胎。

本文是對唯品會訂單庫重構——採用分庫分表策略對原訂單庫表進行拆分的粗略總結,在訂單庫重構過程中遇到的問題遠遠超過這些,比如:歷史資料的遷移、各外圍系統的對接等,但這些在公司強大的技術團隊面前,最終都順利的解決,新舊訂單庫順利的切換,給公司快速的業務發展提供堅實的保障。

相關文章