你好,歡迎進(jìn)入江蘇優(yōu)軟數(shù)字科技有限公司官網(wǎng)!
發(fā)布時(shí)間:2023-07-03
瀏覽次數(shù):0
上一篇文章介紹了分庫(kù)分表的幾種表達(dá)方式和玩法,也重點(diǎn)介紹了垂直分庫(kù)帶來(lái)的問(wèn)題和解決技巧。 本篇我們就來(lái)說(shuō)說(shuō)水平分庫(kù)分表的一些技巧。
1、分片技術(shù)的由來(lái) 關(guān)系型數(shù)據(jù)庫(kù)本身就比較容易成為系統(tǒng)性能的困境。 單機(jī)的存儲(chǔ)容量、連接數(shù)、處理能力都非常有限。 數(shù)據(jù)庫(kù)本身的“有狀態(tài)性”使得它不同于Web和應(yīng)用服務(wù)器那么容易擴(kuò)展。 在互聯(lián)網(wǎng)行業(yè)海量數(shù)據(jù)、高并發(fā)訪問(wèn)的考驗(yàn)下,聰明的技術(shù)人員提出了分庫(kù)分表技術(shù)(有的地方稱之為分片)。 同時(shí),流行的分布式系統(tǒng)中間件(如等)都是自己友好且支持的,其原理和思想都與邯鄲不同。 2、分布式全局唯一ID 在很多中小型項(xiàng)目中,我們經(jīng)常直接利用數(shù)據(jù)庫(kù)自??增功能來(lái)生成字段ID,確實(shí)比較簡(jiǎn)單。 但在分庫(kù)分表的環(huán)境下,數(shù)據(jù)分布在不同的分片上,不能利用數(shù)據(jù)庫(kù)的自減特性直接生成數(shù)據(jù),否則不同分片上的數(shù)據(jù)表字段會(huì)重復(fù)。 簡(jiǎn)單介紹一下使用和理解的幾種ID生成算法。 1.(也稱為“雪花算法”)
2. UUID/GUID(通常應(yīng)用程序和數(shù)據(jù)庫(kù)都支持)
3.(類似于UUID)
4.(數(shù)據(jù)庫(kù)生存方法,這些方法都用到)
3. 如何選擇常用分片規(guī)則和策略分片數(shù)組
在開始分片之前,我們首先需要確定分片數(shù)組(也稱為“分片鍵”)。 在很多常見(jiàn)的情況和場(chǎng)景中,都會(huì)使用ID或者時(shí)間數(shù)組來(lái)進(jìn)行分割。 這并不是絕對(duì)的。 我的建議是結(jié)合實(shí)際業(yè)務(wù),通過(guò)對(duì)系統(tǒng)中執(zhí)行的sql語(yǔ)句進(jìn)行統(tǒng)計(jì)分析,選擇表中最常用或者最重要的需要分片的數(shù)組作為分片數(shù)組。
常見(jiàn)的分片規(guī)則
常見(jiàn)的分片策略有隨機(jī)分片和連續(xù)分片,如右圖所示:
當(dāng)需要使用分片數(shù)組進(jìn)行范圍搜索時(shí),連續(xù)分片可以快速定位分片進(jìn)行高效查詢,并且大多數(shù)情況下可以有效防止跨分片查詢的問(wèn)題。 以后如果要擴(kuò)展整個(gè)分片集群,只需要增加節(jié)點(diǎn)即可,不需要遷移其他分片的數(shù)據(jù)。 而且intellij idea 數(shù)據(jù)庫(kù)關(guān)系圖,連續(xù)分片還可能存在數(shù)據(jù)熱點(diǎn)的問(wèn)題。 例如圖中按時(shí)間字段分片的情況,部分節(jié)點(diǎn)可能會(huì)被頻繁查詢和壓力,熱點(diǎn)數(shù)據(jù)節(jié)點(diǎn)就會(huì)陷入困境。 并且有些節(jié)點(diǎn)可能會(huì)存儲(chǔ)歷史數(shù)據(jù),很少需要查詢。
隨機(jī)分片雖然不是隨機(jī)的,但也遵循一定的規(guī)則。 一般我們會(huì)采用Hash取模的方法進(jìn)行分片和分裂,所以有時(shí)也稱為離散分片。 隨機(jī)分片的數(shù)據(jù)比較均勻,不易出現(xiàn)熱點(diǎn)和并發(fā)訪問(wèn)。 而且后期分片集群的擴(kuò)容需要舊數(shù)據(jù)的遷移。 只有使用一致性Hash算法才能很大程度上避免這個(gè)問(wèn)題,所以很多中間件分片集群都使用一致性Hash算法。 離散分片也容易出現(xiàn)跨分片查詢的復(fù)雜問(wèn)題。
數(shù)據(jù)遷移、容量規(guī)劃、擴(kuò)容等問(wèn)題
很少有項(xiàng)目在早期就開始考慮分片設(shè)計(jì),通常是在業(yè)務(wù)快速發(fā)展,面臨性能和存儲(chǔ)困難的時(shí)候,才會(huì)提早規(guī)劃。 為此,不可避免地要考慮歷史數(shù)據(jù)遷移的問(wèn)題。 通常的做法是先通過(guò)程序讀取歷史數(shù)據(jù),然后根據(jù)指定的分片規(guī)則將數(shù)據(jù)寫入到各個(gè)分片節(jié)點(diǎn)。
據(jù)悉,我們需要根據(jù)當(dāng)前的數(shù)據(jù)量和QPS進(jìn)行容量規(guī)劃,并根據(jù)成本因素估算出大概需要的分片數(shù)量(一般建議單個(gè)分片上單表的數(shù)據(jù)量應(yīng)該是不超過(guò)1000W)。
如果采用隨機(jī)分片,則需要考慮后期的擴(kuò)容,相對(duì)來(lái)說(shuō)會(huì)比較麻煩。 如果使用范圍分片,則只需添加節(jié)點(diǎn)即可手動(dòng)擴(kuò)容。
4. 跨分片技術(shù)問(wèn)題 跨分片排序與分頁(yè)
一般來(lái)說(shuō),分頁(yè)需要按照指定的數(shù)組進(jìn)行排序。 當(dāng)排序后的數(shù)組是切片數(shù)組時(shí),我們可以很容易地通過(guò)切片規(guī)則定位到指定的切片,但是當(dāng)排序后的數(shù)組不是切片數(shù)組時(shí),情況會(huì)顯得更加復(fù)雜。 為了最終結(jié)果的準(zhǔn)確性,我們需要對(duì)不同分片節(jié)點(diǎn)上的數(shù)據(jù)進(jìn)行排序返回,對(duì)不同分片返回的結(jié)果集進(jìn)行匯總重新排序,最后返回給用戶。 如右圖所示:
里面的圖片描述的只是最簡(jiǎn)單的情況(取第一頁(yè)的數(shù)據(jù)),看起來(lái)影響不大。 而且,如果要檢索第10頁(yè)的數(shù)據(jù),情況就會(huì)復(fù)雜很多,如右圖所示:
有些讀者可能不太明白為什么不能像獲取第一頁(yè)數(shù)據(jù)那樣簡(jiǎn)單處理(排序并取出前10條后再進(jìn)行合并排序)。 看起來(lái)也不難理解,由于每個(gè)分片節(jié)點(diǎn)中的數(shù)據(jù)可能是隨機(jī)的,為了排序的準(zhǔn)確性,必須對(duì)所有分片節(jié)點(diǎn)的前N頁(yè)數(shù)據(jù)進(jìn)行排序并合并,最后進(jìn)行整體排序。 事實(shí)上,這樣的操作是比較消耗資源的,而且用戶翻頁(yè)越遠(yuǎn)intellij idea 數(shù)據(jù)庫(kù)關(guān)系圖,系統(tǒng)性能就越差。
跨分片的函數(shù)處理
使用Max、Min、Sum、Count等函數(shù)進(jìn)行統(tǒng)計(jì)和估算時(shí),需要先對(duì)每個(gè)分片數(shù)據(jù)源進(jìn)行相應(yīng)的函數(shù)處理,然后對(duì)每個(gè)結(jié)果集進(jìn)行二次處理,最后返回處理結(jié)果。 如右圖所示:
跨分片加入
Join是關(guān)系型數(shù)據(jù)庫(kù)中最常用的功能,而在分片集群中,Join也非常復(fù)雜。 應(yīng)盡可能避免跨分片聯(lián)接查詢(這些場(chǎng)景比之前的跨分片分頁(yè)更復(fù)雜,但對(duì)性能影響很大)。 一般來(lái)說(shuō),有以下幾種方法可以預(yù)防:
全局表
全局表的概念之前在“垂直分庫(kù)”中提到過(guò)。 基本思想是一樣的,就是在每個(gè)分片中放入一些類似于數(shù)據(jù)字典的、可能形成聯(lián)接查詢的表信息,從而防止跨分片聯(lián)接。
內(nèi)質(zhì)網(wǎng)碎片化
在關(guān)系數(shù)據(jù)庫(kù)中,表之間常常存在一些關(guān)聯(lián)關(guān)系。 如果我們能夠先確定關(guān)聯(lián)關(guān)系,并將這些具有關(guān)聯(lián)關(guān)系的表記錄存儲(chǔ)在同一個(gè)分片上,那么就可以防止跨分片連接的問(wèn)題。 在一對(duì)多關(guān)系的情況下,我們一般選擇按照數(shù)據(jù)較多的一側(cè)進(jìn)行拆分。 如右圖所示:
這樣中的訂單表和明細(xì)訂單表就可以直接關(guān)聯(lián)起來(lái)進(jìn)行部分連接查詢,上也是如此。 這些基于ER分片的方法可以有效防止大多數(shù)業(yè)務(wù)場(chǎng)景下的跨分片連接問(wèn)題。
內(nèi)存估計(jì)
隨著Spark內(nèi)存估算的盛行,理論上來(lái)說(shuō),很多跨數(shù)據(jù)源的操作問(wèn)題似乎都能得到解決。 可以將數(shù)據(jù)丟給spark集群進(jìn)行內(nèi)存估算,最后返回估算結(jié)果。
5. 跨分片交易問(wèn)題 跨分片交易也是分布式交易。 如果想了解分布式事務(wù),就需要了解“XA套接字”和“兩階段提交”。 值得一提的是,.5x和5.6x中的xa支持是有問(wèn)題的,會(huì)導(dǎo)致主從數(shù)據(jù)不一致。 直到 5.7x 版本才修復(fù)。 Java應(yīng)用程序可以使用該框架來(lái)實(shí)現(xiàn)XA事務(wù)(J2EE中的JTA)。 有興趣的讀者可以參考《分布式事務(wù)一致性解決方案》,鏈接地址:
6、我們的系統(tǒng)真的需要分庫(kù)分表嗎?
雖然這一點(diǎn)沒(méi)有明確的判斷標(biāo)準(zhǔn),但更多地取決于實(shí)際業(yè)務(wù)情況和經(jīng)驗(yàn)判斷。 根據(jù)筆者的個(gè)人經(jīng)驗(yàn),MySQL單表1000W左右的數(shù)據(jù)通常是沒(méi)有問(wèn)題的(前提是應(yīng)用系統(tǒng)和數(shù)據(jù)庫(kù)的設(shè)計(jì)和優(yōu)化比較好)。 事實(shí)上,不僅是在考慮當(dāng)前的數(shù)據(jù)量和性能時(shí),作為架構(gòu)師,我們需要提前考慮系統(tǒng)半年到一年左右的業(yè)務(wù)衰退情況,對(duì)QPS做出合理的評(píng)估和規(guī)劃,連接數(shù)、數(shù)據(jù)庫(kù)服務(wù)器的容量,提前做好準(zhǔn)備。 如果單臺(tái)機(jī)器很難滿足,又很難從其他方面去優(yōu)化,就意味著需要考慮碎片化。 在這種情況下,可以先刪除數(shù)據(jù)庫(kù)中的自增ID,以便及早做好分片和相鄰數(shù)據(jù)遷移的計(jì)劃。
很多人認(rèn)為“分庫(kù)分表”宜早不宜遲,因?yàn)閾?dān)心公司業(yè)務(wù)發(fā)展得更快,系統(tǒng)變得越來(lái)越復(fù)雜,系統(tǒng)建設(shè)和擴(kuò)展會(huì)更加困難……這樣的說(shuō)法聽起來(lái)很有道理。 這是有道理的,但我的觀點(diǎn)恰恰相反。 對(duì)于關(guān)系型數(shù)據(jù)庫(kù),我認(rèn)為“不能分片就不分片”,除非系統(tǒng)確實(shí)需要,因?yàn)閿?shù)據(jù)庫(kù)分片并不是低成本或者免費(fèi)的。
這里我推薦一種更靠譜的過(guò)渡技術(shù)——“表分區(qū)”。 主流關(guān)系數(shù)據(jù)庫(kù)基本都支持。 邏輯上,不同的分區(qū)仍然是一張表,但在數(shù)學(xué)上是分開的,這可以在一定程度上提高查詢性能,并且對(duì)應(yīng)用程序是透明的,無(wú)需更改任何代碼。 作者一開始負(fù)責(zé)優(yōu)化一個(gè)系統(tǒng)。 主業(yè)務(wù)表有8000W左右的數(shù)據(jù)。 考慮到成本問(wèn)題,通過(guò)“分表”的方式來(lái)完成。
7.總結(jié) 最后,很多讀者想知道當(dāng)前社區(qū)是否有開源免費(fèi)的分庫(kù)分表解決方案,雖然站在巨人的右臂可以省去不少力氣。 目前解決方案主要有兩類:
1、基于應(yīng)用層的DDAL(分布式數(shù)據(jù)庫(kù)訪問(wèn)層)
比較典型的有天貓的半開源TDDL,當(dāng)當(dāng)網(wǎng)的開源JDBC。 分布式數(shù)據(jù)訪問(wèn)層不需要硬件投入,技術(shù)能力較強(qiáng)的大公司一般選擇自行開發(fā)或參考開源框架進(jìn)行二次開發(fā)和定制。 通常對(duì)應(yīng)用程序更具侵入性,從而降低技術(shù)成本和復(fù)雜性。 一般只支持特定的編程語(yǔ)言平臺(tái)(多為Java平臺(tái)),或者只支持特定的數(shù)據(jù)庫(kù)和特定的數(shù)據(jù)訪問(wèn)框架技術(shù)(通常支持MySQL數(shù)據(jù)庫(kù)、JDBC、.NET等框架技術(shù))。
2、數(shù)據(jù)庫(kù)中間件,典型的如mycat(在阿里開源cobar的基礎(chǔ)上做了很多優(yōu)化和改進(jìn),是后起之秀,也支持很多新特性),基于Go語(yǔ)言實(shí)現(xiàn),相對(duì)來(lái)說(shuō)老Atlas(360開源)等等??。 這種中間件在互聯(lián)網(wǎng)企業(yè)中應(yīng)用廣泛。 另外,MySQL 5.x企業(yè)版中官方提供的組件也可以說(shuō)支持分片技術(shù),但國(guó)外很少有公司使用。
中間件也可以稱為“透明網(wǎng)段”,大名鼎鼎的大概就是這個(gè)領(lǐng)域的鼻祖了(MySQL官方提供,僅限于實(shí)現(xiàn)“讀寫分離”)。 中間件通常實(shí)現(xiàn)特定數(shù)據(jù)庫(kù)的網(wǎng)絡(luò)通信契約,模擬真實(shí)的數(shù)據(jù)庫(kù)服務(wù),屏蔽前端真實(shí)的服務(wù)。 一般情況下,應(yīng)用程序可以直接連接中間件。 在執(zhí)行SQL操作時(shí),中間件會(huì)根據(jù)預(yù)定義的分片規(guī)則對(duì)SQL語(yǔ)句進(jìn)行分析和路由,并對(duì)結(jié)果集進(jìn)行重新評(píng)估,最后返回結(jié)果集。 引入數(shù)據(jù)庫(kù)中間件的技術(shù)成本較低,而且對(duì)應(yīng)用程序幾乎沒(méi)有侵入,可以滿足大多數(shù)業(yè)務(wù)。 減少額外的硬件投資和運(yùn)維成本。 同時(shí),中間件本身也存在性能困難和單點(diǎn)故障問(wèn)題。 需要保證中間件本身的高可用性和可擴(kuò)展性。
事實(shí)上,無(wú)論是使用分布式數(shù)據(jù)訪問(wèn)層還是數(shù)據(jù)庫(kù)中間件,都會(huì)帶來(lái)一定的成本和復(fù)雜度,同時(shí)也會(huì)產(chǎn)生一定的性能影響。 因此,讀者需要根據(jù)實(shí)際情況和業(yè)務(wù)發(fā)展需要仔細(xì)考慮和選擇。
最近熱門讀物:
1、
2、
3.
4.
5.
6.
7.
8、
9、
10.
如有侵權(quán)請(qǐng)聯(lián)系刪除!
Copyright ? 2023 江蘇優(yōu)軟數(shù)字科技有限公司 All Rights Reserved.正版sublime text、Codejock、IntelliJ IDEA、sketch、Mestrenova、DNAstar服務(wù)提供商
13262879759
微信二維碼