天天看點

大衆點評訂單分庫分表實踐 轉載:http://mp.weixin.qq.com/s?__biz=MzIxMjE3NTg2NA==&mid=410147285&idx=1&sn=ace46deefdf0661a98f9a30ecb1278ff&scene=5&srcid=0219t0NeY7aoHEL6WWC1HKbv#rd 背景 垂直切分 水準切分

轉載:http://mp.weixin.qq.com/s?__biz=MzIxMjE3NTg2NA==&mid=410147285&idx=1&sn=ace46deefdf0661a98f9a30ecb1278ff&scene=5&srcid=0219t0NeY7aoHEL6WWC1HKbv#rd

背景

訂單單表早已突破兩百G,因查詢次元較多,即使加了兩個從庫,各種索引優化,依然存在很多查詢不理想的情況;加之去年大量的搶購活動的開展,資料庫達到瓶頸,應用隻能通過限速、異步隊列等對其進行保護;同時業務需求層出不窮,原有的訂單模型很難滿足業務需求,但是基于原訂單表的DDL又非常吃力,無法達到業務要求;随着這些問題越來越突出,訂單資料庫的切分就愈發急迫了。

我們的目标是未來十年内不需要擔心訂單容量的問題

垂直切分

先對訂單庫進行垂直切分,将原有的訂單庫分為基礎訂單庫、訂單流程庫等,這篇文章就不展開講了。

大衆點評訂單分庫分表實踐 轉載:http://mp.weixin.qq.com/s?__biz=MzIxMjE3NTg2NA==&mid=410147285&idx=1&sn=ace46deefdf0661a98f9a30ecb1278ff&scene=5&srcid=0219t0NeY7aoHEL6WWC1HKbv#rd 背景 垂直切分 水準切分

水準切分

垂直切分緩解了原來單叢集的壓力,但是在搶購時依然捉襟見肘,并且原有的的訂單模型已經無法滿足業務需求,于是我們設計了一套新的統一訂單模型,為同時滿足C端使用者、B端商戶、客服、營運等的需求,我們分别通過使用者ID和商戶ID進行切分,并通過PUMA同步到一個營運庫

大衆點評訂單分庫分表實踐 轉載:http://mp.weixin.qq.com/s?__biz=MzIxMjE3NTg2NA==&mid=410147285&idx=1&sn=ace46deefdf0661a98f9a30ecb1278ff&scene=5&srcid=0219t0NeY7aoHEL6WWC1HKbv#rd 背景 垂直切分 水準切分

切分政策

1、查詢切分

将id和庫的mapping關系記錄在一個單獨的庫中

大衆點評訂單分庫分表實踐 轉載:http://mp.weixin.qq.com/s?__biz=MzIxMjE3NTg2NA==&mid=410147285&idx=1&sn=ace46deefdf0661a98f9a30ecb1278ff&scene=5&srcid=0219t0NeY7aoHEL6WWC1HKbv#rd 背景 垂直切分 水準切分

優點:id和庫的mapping算法可以随意更改

缺點:引入額外的單點

2、範圍切分

大衆點評訂單分庫分表實踐 轉載:http://mp.weixin.qq.com/s?__biz=MzIxMjE3NTg2NA==&mid=410147285&idx=1&sn=ace46deefdf0661a98f9a30ecb1278ff&scene=5&srcid=0219t0NeY7aoHEL6WWC1HKbv#rd 背景 垂直切分 水準切分

比如按照時間區間或id區間來切分

優點:單表大小可控,天然水準擴充

缺點:無法解決集中寫入瓶頸的問題

3、hash切分

一般采用mod來切分,下面着重講一下mod的政策

大衆點評訂單分庫分表實踐 轉載:http://mp.weixin.qq.com/s?__biz=MzIxMjE3NTg2NA==&mid=410147285&idx=1&sn=ace46deefdf0661a98f9a30ecb1278ff&scene=5&srcid=0219t0NeY7aoHEL6WWC1HKbv#rd 背景 垂直切分 水準切分

資料水準切分後我們希望是一勞永逸或者是易于水準擴充的,是以推薦采用mod 2^n這種一緻性哈希

以統一訂單庫為例,我們分庫分表的方案是32*32的,即通過userId後四位mod 32分到32個庫中,同時再将userId後四位div 32 mod 32将每個庫分為32個表,共計分為1024張表。線上部署情況為8個叢集(主從),每個叢集4個庫。

為什麼說這種方式是易于水準擴充的呢?我們分析如下兩個場景

場景一:資料庫性能達到瓶頸

方法一:

大衆點評訂單分庫分表實踐 轉載:http://mp.weixin.qq.com/s?__biz=MzIxMjE3NTg2NA==&mid=410147285&idx=1&sn=ace46deefdf0661a98f9a30ecb1278ff&scene=5&srcid=0219t0NeY7aoHEL6WWC1HKbv#rd 背景 垂直切分 水準切分

按照現有規則不變,可以直接擴充到32個資料庫叢集

方法二:

大衆點評訂單分庫分表實踐 轉載:http://mp.weixin.qq.com/s?__biz=MzIxMjE3NTg2NA==&mid=410147285&idx=1&sn=ace46deefdf0661a98f9a30ecb1278ff&scene=5&srcid=0219t0NeY7aoHEL6WWC1HKbv#rd 背景 垂直切分 水準切分

如果32個叢集也無法滿足需求,那麼将分庫分表規則調整為(32*2^n)*(32/2^n),可以達到最多1024個叢集

場景二:單表容量達到瓶頸(或者1024已經無法滿足你)

方法:

大衆點評訂單分庫分表實踐 轉載:http://mp.weixin.qq.com/s?__biz=MzIxMjE3NTg2NA==&mid=410147285&idx=1&sn=ace46deefdf0661a98f9a30ecb1278ff&scene=5&srcid=0219t0NeY7aoHEL6WWC1HKbv#rd 背景 垂直切分 水準切分

假如單表都已突破200G,200*1024=200T(按照現有的訂單模型算了算,大概一萬千億訂單,相信這一天,恩,指日可待!),沒關系,32*(32*2^n),這時分庫規則不變,單庫裡的表再進行裂變,當然,在目前訂單這種規則下(用userId後四位 mod)還是有極限的,因為隻有四位,是以最多拆8192個表,至于為什麼隻取了後四位,後面會有篇幅講到。

另外一個次元是通過shopId進行切分,規則8*8和userId比較類似,就不再贅述,需要注意的是shop庫我們僅存儲了訂單主表,用來滿足shop次元的查詢。

唯一ID方案

這個方案也很多,主流的有那麼幾種

1、利用資料庫自增ID

優點:最簡單

缺點:單點風險、單機性能瓶頸

2、利用資料庫叢集并設定相應的步長(Flickr方案)

優點:高可用、ID較簡潔

缺點:需要單獨的資料庫叢集

3、Twitter snowflake

優點:高性能高可用、易拓展

缺點:需要獨立的叢集以及ZK

4、一大波GUID、Random算法

優點:簡單

缺點:生成ID較長,有重複幾率

我們的方案:

為了減少營運成本并減少額外的風險我們排除了所有需要獨立叢集的方案,采用了帶有業務屬性的方案:

時間戳+使用者辨別碼+随機數

有下面幾個好處:

  1. 友善、成本低
  2. 基本無重複的可能
  3. 自帶分庫規則,這裡的使用者辨別碼即為使用者ID的後四位,在查詢的場景下,隻需要訂單号就可以比對到相應的庫表而無需使用者ID,隻取四位是希望訂單号盡可能的短一些,并且評估下來四位已經足夠
  4. 可排序,因為時間戳在最前面

當然也有一些缺點,比如長度稍長,性能要比int/bigint的要稍差等。

其他問題?

  • 事務支援:我們是将整個訂單領域聚合體切分,次元一緻,是以對聚合體的事務是支援的
  • 複雜查詢:垂直切分後,就跟join說拜拜了;水準切分後,查詢的條件一定要在切分的次元内,比如查詢具體某個使用者下的各位訂單等;禁止不帶切分的次元的查詢,即使中間件可以支援這種查詢,可以在記憶體中組裝,但是這種需求往往不應該在線上庫查詢或者可以通過其他方法轉換到切分的次元以實作。

資料遷移

資料庫拆分一般是業務發展到一定規模後的優化和重構,為了支援業務快速上線,很難一開始就分庫分表,垂直拆分還好辦,改改資料源就搞定了,一旦開始水準拆分,資料清洗就是個大問題,為此,我們經曆了以下幾個階段

第一階段:

大衆點評訂單分庫分表實踐 轉載:http://mp.weixin.qq.com/s?__biz=MzIxMjE3NTg2NA==&mid=410147285&idx=1&sn=ace46deefdf0661a98f9a30ecb1278ff&scene=5&srcid=0219t0NeY7aoHEL6WWC1HKbv#rd 背景 垂直切分 水準切分

資料庫雙寫(事務成功以老模型為準),查詢走老模型

每日job資料對賬(通過DW),并将差異補平

通過job導曆史資料

第二階段:

大衆點評訂單分庫分表實踐 轉載:http://mp.weixin.qq.com/s?__biz=MzIxMjE3NTg2NA==&mid=410147285&idx=1&sn=ace46deefdf0661a98f9a30ecb1278ff&scene=5&srcid=0219t0NeY7aoHEL6WWC1HKbv#rd 背景 垂直切分 水準切分

曆史資料導入完畢并且資料對賬無誤

依然是資料庫雙寫,但是事務成功與否以新模型為準,線上查詢切新模型

每日job資料對賬,将差異補平

第三階段:

大衆點評訂單分庫分表實踐 轉載:http://mp.weixin.qq.com/s?__biz=MzIxMjE3NTg2NA==&mid=410147285&idx=1&sn=ace46deefdf0661a98f9a30ecb1278ff&scene=5&srcid=0219t0NeY7aoHEL6WWC1HKbv#rd 背景 垂直切分 水準切分

老模型不再同步寫入,僅當訂單有終态時才會異步補上

此階段隻有離線資料依然依賴老的模型,并且下遊的依賴非常多,待DW改造完就可以完全廢除老模型了

一些思考:

  • 并非所有表都需要水準拆分,要看增長的類型和速度,水準拆分是大招,拆分後會增加開發的複雜度,不到萬不得已不使用
  • 在大規模并發的業務上,盡量做到線上查詢和離線查詢隔離,交易查詢和營運/客服查詢隔離
  • 拆分的次元的選擇很重要,要盡可能在解決拆分前的問題的基礎上,便于開發
  • 資料庫沒你想象的那麼堅強,需要保護,盡量使用簡單的、良好索引的查詢,這樣資料庫整體可控,也易于長期容量規劃以及水準擴充

繼續閱讀