分布式數(shù)據(jù)庫,是近些年來頗受關(guān)注的領(lǐng)域。一方面隨著數(shù)據(jù)規(guī)模不斷增大,數(shù)據(jù)使用場景更為多樣,對底層數(shù)據(jù)庫的要求越來越高;另一方面對數(shù)據(jù)庫的可用性、擴(kuò)展能力等也都提出更高的要求。分布式數(shù)據(jù)庫的出現(xiàn),恰好滿足了上述兩方面的訴求。但當(dāng)用戶選擇使用分布式的第一個(gè)問題,就是如何將之前基于單機(jī)或集中式數(shù)據(jù)庫設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu)遷移到分布式環(huán)境中,核心點(diǎn)就在于數(shù)據(jù)分片的設(shè)計(jì)。這其中的核心要點(diǎn)有兩個(gè):一是選擇什么字段或字段組合作為分片鍵;二是使用什么分片算法來分片。本文嘗試說明第一個(gè)問題。
1. 是否需要設(shè)計(jì)分片
是否需要設(shè)計(jì)分片?相信是大家首要提出的問題,作為一種新架構(gòu)的出現(xiàn),分布式數(shù)據(jù)庫確實(shí)可以解決一些場景問題,但數(shù)據(jù)分片是在設(shè)計(jì)之初就需考慮。是否有一種更為透明的方式解決分片問題呢,這就引出一個(gè)概念—“數(shù)據(jù)分布獨(dú)立性”。它是指用戶或用戶程序使用分布式數(shù)據(jù)庫如同使用集中式數(shù)據(jù)庫那樣,不必關(guān)系全局?jǐn)?shù)據(jù)的分布情況。也就是說全局?jǐn)?shù)據(jù)的邏輯分片、片段的物理位置等情況對用戶和用戶應(yīng)用程序式透明的。因此分布式數(shù)據(jù)庫中分布獨(dú)立性也成為分布透明性。一個(gè)分布式數(shù)據(jù)庫系統(tǒng)可能提供的分布透明性層次越高,用戶編寫應(yīng)用程序越容易。比較理想的情況是,軟件工程師完全不必處理應(yīng)用級別的分片,因?yàn)檫@并不是他們真正的工作。然而,理想很豐滿,現(xiàn)實(shí)很骨感。完全透明的數(shù)據(jù)分片,在部分場景下仍然會(huì)面臨問題,如低延遲、復(fù)雜業(yè)務(wù)、多中心等,這些場景仍然希望能夠精準(zhǔn)控制數(shù)據(jù)分片規(guī)則甚至物理位置。因此,如何設(shè)計(jì)分片策略也就成為新環(huán)境下DBA不得不面對的問題,起碼是在相當(dāng)長的時(shí)間是如此。正如同數(shù)據(jù)庫初學(xué)者需學(xué)習(xí)的范式理論一樣,未來數(shù)據(jù)分片的設(shè)計(jì)也是考驗(yàn)架構(gòu)、研發(fā)及DBA的基本要求之一。
這里稍微展開說明下,分布式數(shù)據(jù)庫的實(shí)現(xiàn)有兩種主要方式,一是分庫分表;一是NewSQL。兩者的對比可參考下圖。具體在分片上,前者通常可提供更為靈活精準(zhǔn)的分片控制,后者則在分片易用性上更具優(yōu)勢。

2. 如何選擇分片字段
數(shù)據(jù)分片的設(shè)計(jì)上需考慮兩點(diǎn):一是分片字段的選擇;二是對應(yīng)的分片算法。后續(xù)將重點(diǎn)談及分片字段選擇上,下面先簡單說明下分片算法問題。
1).分片算法

分片算法,常規(guī)的有LIST、RANGE、HASH或自定義算法。根據(jù)各拆分算法特點(diǎn),可進(jìn)行選擇。若范圍均勻可采用HASH,冷熱數(shù)據(jù)明顯可采用RANGE等。同時(shí)可配合一些特性化設(shè)計(jì),如采用二級映射方式解決擴(kuò)縮容問題、特征編碼字段滿足多特征拆分等。針對最為常見的兩個(gè)算法描述如下:
- RANGE
 
通過數(shù)據(jù)的范圍進(jìn)行分庫分表,是最樸實(shí)的一種分庫方案,它也可以和其他分庫分表方案靈活結(jié)合使用。當(dāng)需要使用分片字段進(jìn)行范圍查找時(shí),RANGE分片策略可快速定位數(shù)據(jù)進(jìn)行高效查詢。大多數(shù)情況下有效避免跨分片查詢的問題。在后期擴(kuò)容時(shí),也比較方便,只需要添加節(jié)點(diǎn)即可,無需對其他分片的數(shù)據(jù)進(jìn)行遷移。但這種分布方式容易存在數(shù)據(jù)熱點(diǎn)問題。
- HASH
 
雖然分庫分表的方案眾多,但是Hash分庫分表是最大眾最普遍的方案。隨機(jī)分片其實(shí)并不是隨機(jī),也遵循一定規(guī)則。通常采用HASH取模的方式進(jìn)行分片拆分,所以有時(shí)候也稱為離散分片。隨機(jī)分片的數(shù)據(jù)相對均勻,不容易出現(xiàn)熱點(diǎn)和并發(fā)訪問的瓶頸。但涉及后面數(shù)據(jù)遷移的話,不太方便??墒褂靡恢滦訦ASH算法在很大程度上避免此問題。此外,離散分片也容易面臨跨分片查詢的復(fù)雜問題。
2).分片字段
分片字段的選擇,需涉及的因素很多,列個(gè)腦圖分類下。下面將針對各因素詳細(xì)說明:

- 數(shù)據(jù)結(jié)構(gòu):主鍵或唯一鍵
 
主鍵及唯一鍵,是數(shù)據(jù)庫作為常見的約束,其是為了保證非空且唯一性。在分布式環(huán)境下,通常建議將主鍵或唯一鍵字段作為分片鍵或分片鍵的一部分,否則無法完成約束校驗(yàn);當(dāng)然也有產(chǎn)品支持單獨(dú)約束校驗(yàn)。這里有個(gè)引申問題,就是主鍵設(shè)計(jì)問題,在分布式數(shù)據(jù)庫架構(gòu)下,盡量不要用自增作為表的主鍵,自增性能很差、安全性不高、不適用于分布式架構(gòu)。通??墒褂萌鏤UID或全局發(fā)號器(雪花算法)??傊糜行虻娜治ㄒ惶娲栽?,是分布式數(shù)據(jù)庫主鍵的推薦做法。
- 數(shù)據(jù)結(jié)構(gòu):索引
 
通過分片鍵可以把 SQL 查詢路由到指定的分片,但是在現(xiàn)實(shí)的生產(chǎn)環(huán)境中,業(yè)務(wù)還要通過其他的索引訪問表。針對原有系統(tǒng)的索引需要有單獨(dú)策略。通常的策略是通過索引表的方式,即將索引轉(zhuǎn)化為另一張分片表,對于查詢來說通過二次查詢解決,但顯然這種方式不夠優(yōu)雅。因此,最優(yōu)的設(shè)計(jì)不是創(chuàng)建一個(gè)索引表,而是將索引數(shù)據(jù)融入到分片鍵的信息中,這樣通過查詢的列就能直接知道所在的分片信息。效率更高,查詢可以提前知道數(shù)據(jù)對應(yīng)的分片信息,只需 一次查詢就能獲取想要的結(jié)果??偨Y(jié)下,索引對分片字段的選擇上,沒有直接影響。對于高頻索引查詢,可以考慮通過分片鍵的設(shè)計(jì)上進(jìn)行增強(qiáng)。也可以通過全局二級索引(有些分布式數(shù)據(jù)庫支持)來實(shí)現(xiàn)或針對分片內(nèi)做普通索引。
- 數(shù)據(jù)結(jié)構(gòu):字段類型
 
作為分片鍵的字段,通常選擇較為簡單的數(shù)據(jù)類型字段,可以提高效率,如常見的數(shù)字、日期、文本等,對復(fù)雜字段如LOB、JSON等不推薦使用。此外,在設(shè)計(jì)時(shí)需考慮分片字段的類型穩(wěn)定,盡量不要發(fā)生DDL變更。
- 數(shù)據(jù)特征:表規(guī)模
 
表規(guī)模是是否使用分片的關(guān)鍵因素之一。一旦表做了分片后,勢必會(huì)造成一定的“功能退化”,如能采取其他方式縮小表的大小,盡量優(yōu)先其他方式??赏ㄟ^表的全生命周期規(guī)劃,如常規(guī)的數(shù)據(jù)歸檔、壓縮、轉(zhuǎn)儲(chǔ)、清理策略,減少數(shù)據(jù)量;或者利用數(shù)據(jù)庫內(nèi)置的如表分區(qū)、垂直分表等策略有效減小表的大小。
- 數(shù)據(jù)特征:離散度
 
這里說的離散度是指按某個(gè)字段或字段組合后,應(yīng)用分片算法后,數(shù)據(jù)是否足夠分散。數(shù)據(jù)分片的初衷就是減少表的規(guī)模,盡量做到數(shù)據(jù)打散是其根本原則之一。這里需要統(tǒng)計(jì)數(shù)據(jù)拆分后離散程度,盡量選擇能充分打散的字段作為分片鍵。這里需注意,如果選擇字段是帶有業(yè)務(wù)特征,還要關(guān)注未來業(yè)務(wù)變化對它的影響。
- 訪問特征:可變化性
 
選擇固定、不再變化的字段作為分片鍵。雖然有些分布式數(shù)據(jù)庫也支持分片鍵的修改,但畢竟修改后會(huì)涉及數(shù)據(jù)移動(dòng),成本代價(jià)很高;還是優(yōu)選不變的字段為好。
- 訪問特征:事務(wù)隔離
 
盡量選擇按字段拆分后的數(shù)據(jù),對數(shù)據(jù)的變化處理可集中在分片內(nèi)解決。這樣大量的業(yè)務(wù)變化是可以通過本地事務(wù)完成,開銷比全局的要小很多,效率也高。
- 訪問特征:數(shù)據(jù)過濾與關(guān)聯(lián)
 
如此字段經(jīng)常作為數(shù)據(jù)篩選字段被頻繁使用,且選擇率很好,可優(yōu)先作為分片字段。另一種情況則是作為與其他關(guān)聯(lián)表聯(lián)合使用,優(yōu)先選擇那些參與到關(guān)聯(lián)操作的字段為佳。盡量是數(shù)據(jù)在關(guān)聯(lián)后,能在本地完成join動(dòng)作,減少數(shù)據(jù)shuffle或上移匯聚類的操作??赏ㄟ^對系統(tǒng)中執(zhí)行的SQL進(jìn)行統(tǒng)計(jì)分析,選擇出需要分片那個(gè)表中最頻繁被使用到或最為重要的字段類分片。這其中可能包含一些來自O(shè)LAP類的查詢,可將此部分SQL排除在外。
- 分片字段順序
 
如涉及多個(gè)字段作為分片鍵的話,順序因素一般沒有什么影響。主要是針對分片算法,可利用字段做分片即可。但對于復(fù)合分片的情況,是要考慮分片字段的主次關(guān)系的。















 
 
 











 
 
 
 