在线不卡日本ⅴ一区v二区_精品一区二区中文字幕_天堂v在线视频_亚洲五月天婷婷中文网站

  • <menu id="lky3g"></menu>
  • <style id="lky3g"></style>
    <pre id="lky3g"><tt id="lky3g"></tt></pre>

    分布式數(shù)據(jù)庫(kù):如何正確選擇分片鍵?

    分布式數(shù)據(jù)庫(kù):如何正確選擇分片鍵?

    我們知道分布式數(shù)據(jù)庫(kù)是將數(shù)據(jù)打散到不同節(jié)點(diǎn)上存儲(chǔ),從而提升性能與可靠性。那么今天我們來(lái)看看在分布式數(shù)據(jù)庫(kù)中,一個(gè)非常重要的設(shè)計(jì):正確地把數(shù)據(jù)分片,充分發(fā)揮分布式數(shù)據(jù)庫(kù)架構(gòu)的優(yōu)勢(shì)。

    選出分片鍵

    在對(duì)表中的數(shù)據(jù)進(jìn)行分片時(shí),首先要選出一個(gè)分片鍵(Shard Key),即用戶可以通過(guò)這個(gè)字段進(jìn)行數(shù)據(jù)的水平拆分。

    對(duì)于我們之前使用的電商業(yè)務(wù)訂單表orders,其表結(jié)構(gòu)如下所示:

    CREATE TABLE `orders` ( `O_ORDERKEY` int NOT NULL, `O_CUSTKEY` int NOT NULL, `O_ORDERSTATUS` char(1) NOT NULL, `O_TOTALPRICE` decimal(15,2) NOT NULL, `O_ORDERDATE` date NOT NULL, `O_ORDERPRIORITY` char(15) NOT NULL, `O_CLERK` char(15) NOT NULL, `O_SHIPPRIORITY` int NOT NULL, `O_COMMENT` varchar(79) NOT NULL, PRIMARY KEY (`O_ORDERKEY`), KEY `idx_custkey_orderdate` (`O_CUSTKEY`,`O_ORDERDATE`), KEY `ORDERS_FK1` (`O_CUSTKEY`), KEY `idx_custkey_orderdate_totalprice` (`O_CUSTKEY`,`O_ORDERDATE`,`O_TOTALPRICE`), KEY `idx_orderdate` (`O_ORDERDATE`), KEY `idx_orderstatus` (`O_ORDERSTATUS`), CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`O_CUSTKEY`) REFERENCES `customer` (`C_CUSTKEY`)) ENGINE=InnoDB

    對(duì)于類似淘寶、京東、拼多多這樣業(yè)務(wù)體量的應(yīng)用來(lái)說(shuō),單實(shí)例 MySQL 數(shù)據(jù)庫(kù)在性能和存儲(chǔ)容量上肯定無(wú)法滿足“雙 11、618 ”大促的要求,所以要改造成分布式數(shù)據(jù)庫(kù)架構(gòu)。

    而第一步就是要對(duì)表選出一個(gè)分片鍵,然后進(jìn)行分布式架構(gòu)的設(shè)計(jì)。

    對(duì)于上面的表orders,可以選擇的分片鍵有:o_orderkey、o_orderdate、也可以是o_custkey。在選出分片鍵后,就要選擇分片的算法,比較常見(jiàn)的有 RANGE 和 HASH 算法。

    JAVA日知錄寫(xiě)代碼的架構(gòu)師,做架構(gòu)的程序員! 實(shí)戰(zhàn)、源碼、數(shù)據(jù)庫(kù)、架構(gòu)…只要你來(lái),你想了解的這里都有!203篇原創(chuàng)內(nèi)容

    公眾號(hào)

    比如,表 orders,選擇分片鍵 o_orderdate,根據(jù)函數(shù) YEAR 求出訂單年份,然后根據(jù)RANGE 算法進(jìn)行分片,這樣就能設(shè)計(jì)出基于 RANGE 分片算法的分布式數(shù)據(jù)庫(kù)架構(gòu):

    從圖中我們可以看到,采用 RANGE 算法進(jìn)行分片后,表 orders 中,1992 年的訂單數(shù)據(jù)存放在分片 1 中、1993 年的訂單數(shù)據(jù)存放在分片 2 中、1994 年的訂單數(shù)據(jù)存放在分片 3中,依次類推,如果要存放新年份的訂單數(shù)據(jù),追加新的分片即可。

    不過(guò),RANGE 分片算法在分布式數(shù)據(jù)庫(kù)架構(gòu)中,是一種非常糟糕的算法,因?yàn)閷?duì)于分布式架構(gòu),通常希望能解決傳統(tǒng)單實(shí)例數(shù)據(jù)庫(kù)兩個(gè)痛點(diǎn):

    • 性能可擴(kuò)展,通過(guò)增加分片節(jié)點(diǎn),性能可以線性提升;
    • 存儲(chǔ)容量可擴(kuò)展,通過(guò)增加分片節(jié)點(diǎn),解決單點(diǎn)存儲(chǔ)容量的數(shù)據(jù)瓶頸。

    那么對(duì)于訂單表 orders 的 RANGE 分片算法來(lái)說(shuō),你會(huì)發(fā)現(xiàn)以上兩點(diǎn)都無(wú)法實(shí)現(xiàn),因?yàn)楫?dāng)年的數(shù)據(jù)依然存儲(chǔ)在一個(gè)分片上(即熱點(diǎn)還是存在于一個(gè)數(shù)據(jù)節(jié)點(diǎn)上)。

    如果繼續(xù)拆細(xì)呢?比如根據(jù)每天進(jìn)行 RANGE 分片?這樣的確會(huì)好一些,但是對(duì)“雙 11、618”這樣的大促來(lái)說(shuō),依然是單分片在工作,熱點(diǎn)依然異常集中。

    所以在分布式架構(gòu)中,RANGE 分區(qū)算法是一種比較糟糕的算法。但它也有好處:可以方便數(shù)據(jù)在不同機(jī)器間進(jìn)行遷移(migrate),比如要把分片 2 中 1992 年的數(shù)據(jù)遷移到分片 1,直接將表進(jìn)行遷移就行。

    而對(duì)海量并發(fā)的 OLTP 業(yè)務(wù)來(lái)說(shuō),一般推薦用 HASH 的分區(qū)算法。這樣分片的每個(gè)節(jié)點(diǎn)都可以有實(shí)時(shí)的訪問(wèn),每個(gè)節(jié)點(diǎn)負(fù)載都能相對(duì)平衡,從而實(shí)現(xiàn)性能和存儲(chǔ)層的線性可擴(kuò)展。

    我們來(lái)看表 orders 根據(jù) o_orderkey 進(jìn)行 HASH 分片,分片算法如下:

    在上述分片算法中,分片鍵是 o_orderkey,總的分片數(shù)量是 4(即把原來(lái) 1 份數(shù)據(jù)打散到 4 張表中),具體來(lái)講,分片算法是將 o_orderkey 除以 4 進(jìn)行取模操作

    最終,將表orders 根據(jù) HASH 算法進(jìn)行分布式設(shè)計(jì)后的結(jié)果如下圖所示:

    可以看到,對(duì)于訂單號(hào)除以 4,余數(shù)為 0 的數(shù)據(jù)存放在分片 1 中,余數(shù)為 1 的數(shù)據(jù)存放在分片 2 中,余數(shù)為 2 的數(shù)據(jù)存放在分片 3 中,以此類推。

    這種基于 HASH 算法的分片設(shè)計(jì)才能較好地應(yīng)用于大型互聯(lián)網(wǎng)業(yè)務(wù),真正做到分布式數(shù)據(jù)庫(kù)架構(gòu)彈性可擴(kuò)展的設(shè)計(jì)要求。

    但是,表 orders 分區(qū)鍵選擇 o_orderkey 是最好地選擇嗎?并不是。

    我們看一下庫(kù)中的其他表,如表 customer、lineitem,這三張表應(yīng)該是經(jīng)常一起使用的,比如查詢用戶最近的訂單明細(xì)。

    如果用 o_orderkey 作分區(qū)鍵,那么 lineitem 可以用 l_orderkey 作為分區(qū)鍵,但這時(shí)會(huì)發(fā)現(xiàn)表customer 并沒(méi)有訂單的相關(guān)信息,即無(wú)法使用訂單作為分片鍵。

    如果表 customer 選擇另一個(gè)字段作為分片鍵,那么業(yè)務(wù)數(shù)據(jù)無(wú)法做到單元化,也就是對(duì)于表customer、orders、lineitem,分片數(shù)據(jù)在同一數(shù)據(jù)庫(kù)實(shí)例上。

    所以,如果要實(shí)現(xiàn)分片數(shù)據(jù)的單元化,最好的選擇是把用戶字段作為分區(qū)鍵,在表 customer 中就是將 c_custkey 作為分片鍵,表orders 中將 o_custkey 作為分片鍵,表 lineitem 中將 l_custkey 作為分片鍵:

    這樣做的好處是:根據(jù)用戶維度進(jìn)行查詢時(shí),可以在單個(gè)分片上完成所有的操作,不用涉及跨分片的訪問(wèn),如下面的 SQL:

    SELECT * FROM ordersINNER JOIN lineitem ON o_orderkey = l_orderkeyINNER JOIN customer ON o_custkey = c_custkeyWHERE o_custkey = 1ORDER BY o_orderdate DESC LIMIT 10

    所以,分布式數(shù)據(jù)庫(kù)架構(gòu)設(shè)計(jì)的原則是:選擇一個(gè)適合的分片鍵和分片算法,把數(shù)據(jù)打散,并且業(yè)務(wù)的絕大部分查詢都是根據(jù)分片鍵進(jìn)行訪問(wèn)。

    那為什么互聯(lián)網(wǎng)業(yè)務(wù)這么適合進(jìn)行分布式架構(gòu)的設(shè)計(jì)呢?因?yàn)榛ヂ?lián)網(wǎng)業(yè)務(wù)大部分是 To C 業(yè)務(wù),分片鍵就是用戶的 ID,業(yè)務(wù)的大部分訪問(wèn)都是根據(jù)用戶 ID 進(jìn)行查詢,比如:

    • 查看某個(gè)用戶下的微博/短視頻;
    • 查看某個(gè)用戶的商品信息/購(gòu)買記錄;
    • 查看某個(gè)用戶自己的余額信息。

    學(xué)完分片鍵的選擇后,接著就是規(guī)劃分片,也就我們經(jīng)常提到的分庫(kù)分表。

    分庫(kù)分表

    說(shuō)了這么久分片,分片到底是什么呢?其實(shí),分片本質(zhì)是一張張表,而不是數(shù)據(jù)庫(kù)實(shí)例,只是每個(gè)分片是在 MySQL 數(shù)據(jù)庫(kù)實(shí)例中,嚴(yán)格來(lái)說(shuō):

    分片 = 實(shí)例 + 庫(kù) + 表 = ip@port:db_name:table_name

    對(duì)于前面的表orders,假設(shè)根據(jù) HASH 算法進(jìn)行分片,那么可以進(jìn)行如下的分庫(kù)分表設(shè)計(jì):

  • 每個(gè)分片的表名庫(kù)名都一樣,如庫(kù) tpch,表名 orders;
  • 每個(gè)分片的庫(kù)名不一樣,表名一樣,如庫(kù)名 tpch01、tpch02、tpch03、tpch04,表名orders;
  • 每個(gè)分片的表名不一樣,庫(kù)名一樣,如庫(kù)名 tpch,表名分別為 orders01、orders02、orders03、orders04;
  • 每個(gè)分片的庫(kù)名不一樣,表名也不一樣,如分片 1 的表在庫(kù)名 tpch01下,表名為oders01;分片 2 的表名在庫(kù)名 tpch02,表名為 orders02;分片 3 的表名在庫(kù)名tpch03,表名為 orders03;分片 3 的表名在庫(kù)名 tpch04,表名為 orders04。
  • 在這 4 種分庫(kù)分表規(guī)則中,最推薦的是第 4 種,也是我們通常意義說(shuō)的分庫(kù)分表,這樣做的好處有以下幾點(diǎn):

    • 不同分片的數(shù)據(jù)可以在同一 MySQL 數(shù)據(jù)庫(kù)實(shí)例上,便于做容量的規(guī)劃和后期的擴(kuò)展;
    • 同一分片鍵的表都在同一庫(kù)下,方便做整體數(shù)據(jù)的遷移和擴(kuò)容。

    如果根據(jù)第 4 種標(biāo)準(zhǔn)的分庫(kù)分表規(guī)范,那么分布式 MySQL 數(shù)據(jù)庫(kù)的架構(gòu)可以是這樣:

    有沒(méi)有發(fā)現(xiàn),按上面這樣的分布式設(shè)計(jì),數(shù)據(jù)分片完成后,所有的庫(kù)表依然是在同一個(gè) MySQL實(shí)例上!??!

    牢記,分布式數(shù)據(jù)庫(kù)并不一定要求有很多個(gè)實(shí)例,最基本的要求是將數(shù)據(jù)進(jìn)行打散分片。接著,用戶可以根據(jù)自己的需要,進(jìn)行擴(kuò)縮容,以此實(shí)現(xiàn)數(shù)據(jù)庫(kù)性能和容量的伸縮性。這才是分布式數(shù)據(jù)庫(kù)真正的魅力所在。

    對(duì)于上述的分布式數(shù)據(jù)庫(kù)架構(gòu),一開(kāi)始我們將 4 個(gè)分片數(shù)據(jù)存儲(chǔ)在一個(gè) MySQL 實(shí)例上,但是如果遇到一些大促活動(dòng),可以對(duì)其進(jìn)行擴(kuò)容,比如把 4 個(gè)分片擴(kuò)容到 4 個(gè)MySQL實(shí)例上:

    如果完成了大促活動(dòng),又可以對(duì)資源進(jìn)行回收,將分片又都放到一臺(tái) MySQL 實(shí)例上,這就是對(duì)資源進(jìn)行縮容。

    總的來(lái)說(shuō),對(duì)分布式數(shù)據(jù)庫(kù)進(jìn)行擴(kuò)縮容在互聯(lián)網(wǎng)公司是一件常見(jiàn)的操作,比如對(duì)阿里來(lái)說(shuō),每年下半年 7 月開(kāi)始,他們就要進(jìn)行雙 11 活動(dòng)的容量評(píng)估,然后根據(jù)評(píng)估結(jié)果規(guī)劃數(shù)據(jù)庫(kù)的擴(kuò)容。

    一般來(lái)說(shuō),電商的雙 11 活動(dòng)后,還有雙 12、新年、春節(jié),所以一般會(huì)持續(xù)到過(guò)完年再對(duì)數(shù)據(jù)庫(kù)進(jìn)行縮容。接下來(lái),我們來(lái)看看如何進(jìn)行擴(kuò)縮容。

    擴(kuò)縮容

    在 HASH 分片的例子中,我們把數(shù)據(jù)分片到了 4 個(gè)節(jié)點(diǎn),然而在生產(chǎn)環(huán)境中,為了方便之后的擴(kuò)縮容操作,推薦一開(kāi)始就把分片的數(shù)量設(shè)置為不少于 1000 個(gè)。

    不用擔(dān)心分片數(shù)量太多,因?yàn)榉制?1 個(gè)還是 1000 個(gè),管理方式都是一樣的,但是 1000 個(gè),意味著可以擴(kuò)容到 1000 個(gè)實(shí)例上,對(duì)于一般業(yè)務(wù)來(lái)說(shuō),1000 個(gè)實(shí)例足夠滿足業(yè)務(wù)的需求了(BTW,網(wǎng)傳阿里某核心業(yè)務(wù)的分布式數(shù)據(jù)庫(kù)分片數(shù)量為 10000個(gè))。

    如果到了 1000 個(gè)分片依然無(wú)法滿足業(yè)務(wù)的需求,這時(shí)能不能拆成 2000 個(gè)分片呢?從理論上來(lái)說(shuō)是可以的,但是這意味著需要對(duì)一張表中的數(shù)據(jù)進(jìn)行邏輯拆分,這個(gè)工作非常復(fù)雜,通常不推薦。

    所以,一開(kāi)始一定要設(shè)計(jì)足夠多的分片。在實(shí)際工作中,我遇到很多次業(yè)務(wù)將分片數(shù)量從 32、64 拆成 256、512。每次這樣的工作,都是扒一層皮,太不值得。所以,做好分布式數(shù)據(jù)庫(kù)設(shè)計(jì)的工作有多重要!

    那么擴(kuò)容在 MySQL 數(shù)據(jù)庫(kù)中如何操作呢?其實(shí),本質(zhì)是搭建一個(gè)復(fù)制架構(gòu),然后通過(guò)設(shè)置過(guò)濾復(fù)制,僅回放分片所在的數(shù)據(jù)庫(kù)就行,這個(gè)數(shù)據(jù)庫(kù)配置在從服務(wù)器上大致進(jìn)行如下配置:

    # 分片1從服務(wù)器配置replicate_do_db =”tpch01″

    所以在進(jìn)行擴(kuò)容時(shí),首先根據(jù)下圖的方式對(duì)擴(kuò)容的分片進(jìn)行過(guò)濾復(fù)制的配置:

    然后再找一個(gè)業(yè)務(wù)低峰期,將業(yè)務(wù)的請(qǐng)求轉(zhuǎn)向新的分片,完成最終的擴(kuò)容操作:

    至于縮容操作,本質(zhì)就是擴(kuò)容操作的逆操作,這里就不再多說(shuō)了。

    總結(jié)

    今天這一講,我們學(xué)習(xí)了分布式數(shù)據(jù)庫(kù)架構(gòu)設(shè)計(jì)中的分片設(shè)計(jì),也就是我們經(jīng)常聽(tīng)說(shuō)的分庫(kù)分表設(shè)計(jì)。希望通過(guò)本講,你能牢牢掌握以下內(nèi)容:

    • 分布式數(shù)據(jù)庫(kù)數(shù)據(jù)分片要先選擇一個(gè)或多個(gè)字段作為分片鍵;
    • 分片鍵的要求是業(yè)務(wù)經(jīng)常訪問(wèn)的字段,且業(yè)務(wù)之間的表大多能根據(jù)這個(gè)分片鍵進(jìn)行單元化;
    • 如果選不出分片鍵,業(yè)務(wù)就無(wú)法進(jìn)行分布式數(shù)據(jù)庫(kù)的改造;
    • 選擇完分片鍵后,就要選擇分片算法,通常是 RANGE 或 HASH 算法;
    • 海量 OLTP 業(yè)務(wù)推薦使用 HASH 算法,強(qiáng)烈不推薦使用 RANGE 算法;
    • 分片鍵和分片算法選擇完后,就要進(jìn)行分庫(kù)分表設(shè)計(jì),推薦不同庫(kù)名表名的設(shè)計(jì),這樣能方便后續(xù)對(duì)分片數(shù)據(jù)進(jìn)行擴(kuò)縮容;
    • 實(shí)際進(jìn)行擴(kuò)容時(shí),可以使用過(guò)濾復(fù)制,僅復(fù)制需要的分片數(shù)據(jù)。
    鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場(chǎng),版權(quán)歸原作者所有,如有侵權(quán)請(qǐng)聯(lián)系管理員(admin#wlmqw.com)刪除。
    上一篇 2022年6月20日 13:01
    下一篇 2022年6月20日 13:01

    相關(guān)推薦

    聯(lián)系我們

    聯(lián)系郵箱:admin#wlmqw.com
    工作時(shí)間:周一至周五,10:30-18:30,節(jié)假日休息