分庫分表問題探討
發(fā)布日期:2022/9/8 9:08:59 瀏覽量:
數(shù)據(jù)庫可以通過主從復(fù)制將數(shù)據(jù)復(fù)制多份實現(xiàn)讀寫分離,讀走從庫,寫走主庫,應(yīng)對量并發(fā)讀的能力,同時提高數(shù)據(jù)安全性。
但是對于單個表,還存在很多問題,比如:
- 單表記錄過多,字段加上索引,索引的占用空間也會越來越大,影響查詢。
- 不同的數(shù)據(jù),用戶,商品等都存放在?個庫中,甚至一張表中,?旦崩潰,全部模塊都受到影響。
因此可以做分庫分表,將問題隔離在某一張表或者某一個庫中,降低單個庫的壓力?;舅枷胧且勒漳?種策略將數(shù)據(jù)盡量平均地分配到多個數(shù)據(jù)庫節(jié)點或者多個表中。分庫分表后,不同的節(jié)點值保存部分數(shù)據(jù),所有庫表加到一塊就是所有的數(shù)據(jù)。拆分分為垂直拆分和水平拆分。
一些電商系統(tǒng)中的實踐就是:不同的商品放在不同的庫,高流量下來比如雙11,即使?部分商品?法瀏覽下單,也能保證大部分商品沒問題。
一、垂直拆分
原則?般是專庫專用,注重業(yè)務(wù)相關(guān)性,將數(shù)據(jù)庫的表分離到不同的庫中,比如用戶關(guān)系放在用戶庫,內(nèi)容放在內(nèi)容庫。
但是水平拆分無法解決單張表記錄量增長的問題,?如視頻或者直播業(yè)務(wù)中,用戶會在視頻播放過程中發(fā)送大量的彈幕,會有數(shù)據(jù)膨脹的問題。因此需要做單張表拆分。
二、水平拆分
水平拆分更注重數(shù)據(jù)的特點,將單表內(nèi)具有一定相關(guān)性的記錄拆分到不同的表或者庫中。但是要考慮拆分規(guī)則,也就是如何根據(jù)單條記錄定位到庫。
可選方案有:
- 根據(jù)字段進行hash值計算,比如根據(jù)用戶ID做hash,相當(dāng)于把ID打散,然后對數(shù)據(jù)庫的個數(shù)取余,得到的值就是記錄對應(yīng)要存放的庫。
- 用常規(guī)字段做區(qū)間劃分,比如根據(jù)記錄的創(chuàng)建時間,?條記錄是1?創(chuàng)建,插?和查找的時候?創(chuàng)建時間這個字段先去找到對應(yīng)的1號庫。但是這種方式有明顯的熱點現(xiàn)象。?如6月11月是購物的熱點事件,對應(yīng)的兩個表或者庫的QPS就會更多。
三、分庫分表引入的問題
主要是水平分庫
1、區(qū)分鍵的問題
分區(qū)鍵問題:具體的表現(xiàn)是,如果把記錄存放在哪個庫是依據(jù)主鍵ID進行hash取余計算得來的,也就是分表的時候是根據(jù)主鍵定位到具體的庫。那么后續(xù)如果根據(jù)非主鍵,比如根據(jù)用戶名去查找記錄,現(xiàn)在只根據(jù)用戶名去定位記錄,就要先找到主鍵ID,否則就要把所有庫掃描一遍。
解決辦法之?就是:建立?個額外的映射表。這個表只有兩個字段用戶名和主鍵ID,查詢記錄時候先根據(jù)用戶名去找ID,然后再根據(jù)ID去定位到庫表,雖然這個映射表會有?定的存儲消耗,但是畢竟只有兩個字段,相對來說可以接受。
2、數(shù)據(jù)庫特性難以實現(xiàn)
聚合操作:在未分庫分表之前查詢記錄總數(shù)時只需要在SQL中執(zhí)?count()聚合函數(shù)即可,現(xiàn)在數(shù)據(jù)被分散到多個庫表中,要么對所有的表都計算一遍或者比方說將計數(shù)的數(shù)據(jù)單獨在?張表中或者記錄在Redis??單獨記錄。
3、全局ID問題
水平分表之后引入的另外一個比較嚴重的問題就是如何選擇全局唯一ID作為主鍵。
四、如何選擇全局ID
1、業(yè)務(wù)字段作為主鍵
選擇業(yè)務(wù)字段作為主鍵,?如?份證,郵箱或者?機號等,但是并不通?
- 比如?份證,對于一些匿名登陸產(chǎn)生的記錄,則?法使用身份證證作為主鍵
- 比如郵箱手機號,一般郵箱和手機號還存在變更的可能
2、UUID作為全局
主鍵要保證全局唯?性,保證每個機器上生成的記錄都不會沖突,UUID類似的隨機生成可以保證唯一,但是無法保證一定遞增。
為什么要保證遞增?
- 因為可能會根據(jù)ID排序,?如彈幕系統(tǒng),會按照倒序看最新發(fā)送的彈幕。如果ID不能保證遞增,只能額外用時間字段記錄時間戳,對所有的記錄再排序。
- 另外B+樹的數(shù)據(jù)頁是葉內(nèi)記錄按照ID遞增,如果ID非遞增,則可能導(dǎo)致記錄非尾部插入最終數(shù)據(jù)頁分裂,降低插?的性能。
3、雪花算法計算全局ID
Snowflake的核心思想是將64bit的?進制數(shù)字分成若干部分,每?部分都存儲有特定含義的數(shù)據(jù),比如說時間戳、機器ID、序列號等等,最終?成全局唯?的有序ID。
比如當(dāng)前機器上,第2臺機器,時間戳第32毫秒,有12個序列號位,當(dāng)前時間戳下可以生成2^12個序號ID,基本可以滿足要求。
雪花算法缺點:
- 比較依賴系統(tǒng)時間戳,重啟服務(wù)器就會機器編號,時間不準可能導(dǎo)致生成重復(fù)ID,當(dāng)?成重復(fù)ID,可以暫停發(fā)號,進行時鐘校準。
- ?如服務(wù)的QPS并不?,時間間隔是毫秒為單位,導(dǎo)致當(dāng)前毫秒下可以生成2^12個序號ID,序列號只了1-10的前幾個ID,可以序列號的起始號隨機或者擴?時間間隔為s。
五、總結(jié)
1、什么時候進行分庫分表
很多說法是:
- 1、表中記錄超過2000萬行,性能會出現(xiàn)瓶頸,主要是因為一個三級的
- 2、單標記錄超過500萬行或者表的實際存儲超過2GB、
實際也跟MySQL的配置和機器的硬件性能有關(guān),mysql為了提高查詢性能會把表的索引非葉子節(jié)點(指針和key)都加載到內(nèi)存中,如果設(shè)置的內(nèi)存足夠大,索引文件都能加載到內(nèi)存中,不會有問題,一個3層的B+樹索引可以滿足千萬級別的數(shù)據(jù)存儲。但是當(dāng)單表的記錄量超過這個上限,內(nèi)存無法完全存放索引,查詢就會產(chǎn)生多余的磁盤IO,從而性能下降。
2、原則
分庫分表會對使?數(shù)據(jù)庫帶來?些不便,但是相比它所帶來的擴展性和性能??的提升還是需要做的,因為經(jīng)歷過分庫分表后的系統(tǒng),才能夠突破單機的容量和請求量的瓶頸。
對于分庫分表的原則主要有以下幾點:
- 1、如果在性能上沒有瓶頸點那么就盡量不做分庫分表;
- 2、如果要做,就盡量?次到位基本能夠滿足幾年內(nèi)很長一段時間的需求。
馬上咨詢: 如果您有業(yè)務(wù)方面的問題或者需求,歡迎您咨詢!我們帶來的不僅僅是技術(shù),還有行業(yè)經(jīng)驗積累。
QQ: 39764417/308460098 Phone: 13 9800 1 9844 / 135 6887 9550 聯(lián)系人:石先生/雷先生