大众点评订单系统分库分表实践
原大眾點(diǎn)評(píng)的訂單單表早就已經(jīng)突破兩百G,由于查詢維度較多,即使加了兩個(gè)從庫(kù),優(yōu)化索引,仍然存在很多查詢不理想的情況。去年大量搶購(gòu)活動(dòng)的開(kāi)展,使數(shù)據(jù)庫(kù)達(dá)到瓶頸,應(yīng)用只能通過(guò)限速、異步隊(duì)列等對(duì)其進(jìn)行保護(hù);業(yè)務(wù)需求層出不窮,原有的訂單模型很難滿足業(yè)務(wù)需求,但是基于原訂單表的DDL又非常吃力,無(wú)法達(dá)到業(yè)務(wù)要求。隨著這些問(wèn)題越來(lái)越突出,訂單數(shù)據(jù)庫(kù)的切分就愈發(fā)急迫了。
這次切分,我們的目標(biāo)是未來(lái)十年內(nèi)不需要擔(dān)心訂單容量的問(wèn)題。
先對(duì)訂單庫(kù)進(jìn)行垂直切分,將原有的訂單庫(kù)分為基礎(chǔ)訂單庫(kù)、訂單流程庫(kù)等,本文就不展開(kāi)講了。
垂直切分緩解了原來(lái)單集群的壓力,但是在搶購(gòu)時(shí)依然捉襟見(jiàn)肘。原有的訂單模型已經(jīng)無(wú)法滿足業(yè)務(wù)需求,于是我們?cè)O(shè)計(jì)了一套新的統(tǒng)一訂單模型,為同時(shí)滿足C端用戶、B端商戶、客服、運(yùn)營(yíng)等的需求,我們分別通過(guò)用戶ID和商戶ID進(jìn)行切分,并通過(guò)PUMA(我們內(nèi)部開(kāi)發(fā)的MySQL binlog實(shí)時(shí)解析服務(wù))同步到一個(gè)運(yùn)營(yíng)庫(kù)。
切分策略
1. 查詢切分
將ID和庫(kù)的Mapping關(guān)系記錄在一個(gè)單獨(dú)的庫(kù)中。
優(yōu)點(diǎn):ID和庫(kù)的Mapping算法可以隨意更改。
缺點(diǎn):引入額外的單點(diǎn)。
2. 范圍切分
比如按照時(shí)間區(qū)間或ID區(qū)間來(lái)切分。
優(yōu)點(diǎn):單表大小可控,天然水平擴(kuò)展。
缺點(diǎn):無(wú)法解決集中寫入瓶頸的問(wèn)題。
3. Hash切分
一般采用Mod來(lái)切分,下面著重講一下Mod的策略。
數(shù)據(jù)水平切分后我們希望是一勞永逸或者是易于水平擴(kuò)展的,所以推薦采用mod 2^n這種一致性Hash。
以統(tǒng)一訂單庫(kù)為例,我們分庫(kù)分表的方案是32*32的,即通過(guò)UserId后四位mod 32分到32個(gè)庫(kù)中,同時(shí)再將UserId后四位Div 32 Mod 32將每個(gè)庫(kù)分為32個(gè)表,共計(jì)分為1024張表。線上部署情況為8個(gè)集群(主從),每個(gè)集群4個(gè)庫(kù)。
為什么說(shuō)這種方式是易于水平擴(kuò)展的呢?我們分析如下兩個(gè)場(chǎng)景。
場(chǎng)景一:數(shù)據(jù)庫(kù)性能達(dá)到瓶頸
方法一
按照現(xiàn)有規(guī)則不變,可以直接擴(kuò)展到32個(gè)數(shù)據(jù)庫(kù)集群。
方法二
如果32個(gè)集群也無(wú)法滿足需求,那么將分庫(kù)分表規(guī)則調(diào)整為(32*2^n)*(32?2^n),可以達(dá)到最多1024個(gè)集群。
場(chǎng)景二:單表容量達(dá)到瓶頸(或者1024已經(jīng)無(wú)法滿足你)
方法:
假如單表都已突破200G,200*1024=200T(按照現(xiàn)有的訂單模型算了算,大概一萬(wàn)千億訂單,相信這一天,嗯,指日可待!),沒(méi)關(guān)系,32*(32*2^n),這時(shí)分庫(kù)規(guī)則不變,單庫(kù)里的表再進(jìn)行裂變,當(dāng)然,在目前訂單這種規(guī)則下(用userId后四位 mod)還是有極限的,因?yàn)橹挥兴奈?#xff0c;所以最多拆8192個(gè)表,至于為什么只取后四位,后面會(huì)有篇幅講到。
另外一個(gè)維度是通過(guò)ShopID進(jìn)行切分,規(guī)則8*8和UserID比較類似,就不再贅述,需要注意的是Shop庫(kù)我們僅存儲(chǔ)了訂單主表,用來(lái)滿足Shop維度的查詢。
唯一ID方案
這個(gè)方案也很多,主流的有那么幾種:
1. 利用數(shù)據(jù)庫(kù)自增ID
優(yōu)點(diǎn):最簡(jiǎn)單。 缺點(diǎn):單點(diǎn)風(fēng)險(xiǎn)、單機(jī)性能瓶頸。
2. 利用數(shù)據(jù)庫(kù)集群并設(shè)置相應(yīng)的步長(zhǎng)(Flickr方案)
優(yōu)點(diǎn):高可用、ID較簡(jiǎn)潔。 缺點(diǎn):需要單獨(dú)的數(shù)據(jù)庫(kù)集群。
3. Twitter Snowflake
優(yōu)點(diǎn):高性能高可用、易拓展。 缺點(diǎn):需要獨(dú)立的集群以及ZK。
4. 一大波GUID、Random算法
優(yōu)點(diǎn):簡(jiǎn)單。 缺點(diǎn):生成ID較長(zhǎng),有重復(fù)幾率。
我們的方案
為了減少運(yùn)營(yíng)成本并減少額外的風(fēng)險(xiǎn)我們排除了所有需要獨(dú)立集群的方案,采用了帶有業(yè)務(wù)屬性的方案: > 時(shí)間戳+用戶標(biāo)識(shí)碼+隨機(jī)數(shù)
有下面幾個(gè)好處:
- 方便、成本低。
- 基本無(wú)重復(fù)的可能。
- 自帶分庫(kù)規(guī)則,這里的用戶標(biāo)識(shí)碼即為用戶ID的后四位,在查詢的場(chǎng)景下,只需要訂單號(hào)就可以匹配到相應(yīng)的庫(kù)表而無(wú)需用戶ID,只取四位是希望訂單號(hào)盡可能的短一些,并且評(píng)估下來(lái)四位已經(jīng)足夠。
- 可排序,因?yàn)闀r(shí)間戳在最前面。
當(dāng)然也有一些缺點(diǎn),比如長(zhǎng)度稍長(zhǎng),性能要比int/bigint的稍差等。
其他問(wèn)題
- 事務(wù)支持:我們是將整個(gè)訂單領(lǐng)域聚合體切分,維度一致,所以對(duì)聚合體的事務(wù)是支持的。
- 復(fù)雜查詢:垂直切分后,就跟join說(shuō)拜拜了;水平切分后,查詢的條件一定要在切分的維度內(nèi),比如查詢具體某個(gè)用戶下的各位訂單等;禁止不帶切分的維度的查詢,即使中間件可以支持這種查詢,可以在內(nèi)存中組裝,但是這種需求往往不應(yīng)該在在線庫(kù)查詢,或者可以通過(guò)其他方法轉(zhuǎn)換到切分的維度來(lái)實(shí)現(xiàn)。
數(shù)據(jù)遷移
數(shù)據(jù)庫(kù)拆分一般是業(yè)務(wù)發(fā)展到一定規(guī)模后的優(yōu)化和重構(gòu),為了支持業(yè)務(wù)快速上線,很難一開(kāi)始就分庫(kù)分表,垂直拆分還好辦,改改數(shù)據(jù)源就搞定了,一旦開(kāi)始水平拆分,數(shù)據(jù)清洗就是個(gè)大問(wèn)題,為此,我們經(jīng)歷了以下幾個(gè)階段。
第一階段
- 數(shù)據(jù)庫(kù)雙寫(事務(wù)成功以老模型為準(zhǔn)),查詢走老模型。
- 每日job數(shù)據(jù)對(duì)賬(通過(guò)DW),并將差異補(bǔ)平。
- 通過(guò)job導(dǎo)歷史數(shù)據(jù)。
第二階段
- 歷史數(shù)據(jù)導(dǎo)入完畢并且數(shù)據(jù)對(duì)賬無(wú)誤。
- 依然是數(shù)據(jù)庫(kù)雙寫,但是事務(wù)成功與否以新模型為準(zhǔn),在線查詢切新模型。
- 每日job數(shù)據(jù)對(duì)賬,將差異補(bǔ)平。
第三階段
- 老模型不再同步寫入,僅當(dāng)訂單有終態(tài)時(shí)才會(huì)異步補(bǔ)上。
- 此階段只有離線數(shù)據(jù)依然依賴?yán)系哪P?#xff0c;并且下游的依賴非常多,待DW改造完就可以完全廢除老模型了。
總結(jié)
并非所有表都需要水平拆分,要看增長(zhǎng)的類型和速度,水平拆分是大招,拆分后會(huì)增加開(kāi)發(fā)的復(fù)雜度,不到萬(wàn)不得已不使用。
在大規(guī)模并發(fā)的業(yè)務(wù)上,盡量做到在線查詢和離線查詢隔離,交易查詢和運(yùn)營(yíng)/客服查詢隔離。
拆分維度的選擇很重要,要盡可能在解決拆分前問(wèn)題的基礎(chǔ)上,便于開(kāi)發(fā)。
數(shù)據(jù)庫(kù)沒(méi)你想象的那么堅(jiān)強(qiáng),需要保護(hù),盡量使用簡(jiǎn)單的、良好索引的查詢,這樣數(shù)據(jù)庫(kù)整體可控,也易于長(zhǎng)期容量規(guī)劃以及水平擴(kuò)展。
最后感謝一下棒棒的DBA團(tuán)隊(duì)和數(shù)據(jù)庫(kù)中間件團(tuán)隊(duì)對(duì)項(xiàng)目的大力協(xié)助!
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的大众点评订单系统分库分表实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Spring Cloud Config的
- 下一篇: 美团集群调度系统HULK技术演进