偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

分庫分表“實踐”大全

運維 數(shù)據(jù)庫運維
分庫分表是個蛋疼的過程,需要考慮數(shù)據(jù)遷移、數(shù)據(jù)同步、數(shù)據(jù)切分等多個工作項,項目bug會持續(xù)到天荒地老。網(wǎng)絡(luò)上搜索到的文章,往往有些錯誤的觀點,只有調(diào)研,沒有實踐。在早些年,我就走過這方面的彎路。本篇文章亦為實踐后的產(chǎn)出,有很大的參考價值。

[[282008]]

分庫分表是個蛋疼的過程,需要考慮數(shù)據(jù)遷移、數(shù)據(jù)同步、數(shù)據(jù)切分等多個工作項,項目bug會持續(xù)到天荒地老。網(wǎng)絡(luò)上搜索到的文章,往往有些錯誤的觀點,只有調(diào)研,沒有實踐。在早些年,我就走過這方面的彎路。本篇文章亦為實踐后的產(chǎn)出,有很大的參考價值。

 

背景

從標題可以看得出來,當時我們只做了分表;還是由于業(yè)務(wù)發(fā)展,截止到現(xiàn)在也做了分庫,目前看來都還比較順利,所以借著腦子還記得清楚來一次復(fù)盤。

先來回顧下整個分庫分表的流程如下:

 

整個過程也很好理解,基本符合大部分公司的一個發(fā)展方向。

很少會有業(yè)務(wù)一開始就會設(shè)計為分庫分表,雖說這樣會減少后續(xù)的坑,但部分公司剛開始都是以業(yè)務(wù)為主。

直到業(yè)務(wù)發(fā)展到單表無法支撐時,自然而然會考慮分表甚至分庫的事情。

于是本篇會作一次總結(jié),之前提過的內(nèi)容可能會再重復(fù)一次。

分表

首先討論下什么樣的情況下適合分表?

根據(jù)我的經(jīng)驗來看,當某張表的數(shù)據(jù)量已經(jīng)達到千萬甚至上億,同時日增數(shù)據(jù)量在 2% 以上。

當然這些數(shù)字并不是絕對的,最重要的還是對這張表的寫入和查詢都已經(jīng)影響到正常業(yè)務(wù)執(zhí)行,比如查詢速度明顯下降,數(shù)據(jù)庫整體 IO 居高不下等。

而談到分表時我們著重討論的還是水平分表;

 

也就是將一張大表數(shù)據(jù)通過某種路由算法將數(shù)據(jù)盡可能的均勻分配到 N 張小表中。

Range

而分表策略也有好幾種,分別適用不同的場景。

首先第一種是按照范圍劃分,比如我們可以將某張表的創(chuàng)建時間按照日期劃分存為月表;也可以將某張表的主鍵按照范圍劃分,比如 【1~10000】在一張表,【10001~20000】在一張表,以此類推。

 

這樣的分表適合需要對數(shù)據(jù)做歸檔處理,比如系統(tǒng)默認只提供近三個月歷史數(shù)據(jù)的查詢功能,這樣也方便操作;只需要把三月之前的數(shù)據(jù)單獨移走備份保存即可)。

這個方案有好處也有弊端:

  • 好處是自帶水平擴展,不需要過多干預(yù)。
  • 缺點是可能會出現(xiàn)數(shù)據(jù)不均勻的情況(比如某個月請求暴增)。

Hash

按照日期這樣的范圍分表固然簡單,但適用范圍還是比較窄;畢竟我們大部分的數(shù)據(jù)查詢都不想帶上時間。

比如某個用戶想查詢他產(chǎn)生的所有訂單信息,這是很常見的需求。

于是我們分表的維度就得改改,分表算法可以采用主流的 hash+mod 的組合。

這是一個經(jīng)典的算法,大名鼎鼎的 HashMap 也是這樣來存儲數(shù)據(jù)。

假設(shè)我們這里將原有的一張大表訂單信息分為 64 張分表:

 

這里的 hash 便是將我們需要分表的字段進行一次散列運算,使得經(jīng)過散列的數(shù)據(jù)盡可能的均勻并且不重復(fù)。

當然如果本身這個字段就是一個整形并且不重復(fù)也可以省略這個步驟,直接進行 Mod 得到分表下標即可。

分表數(shù)量選擇

至于這里的分表數(shù)量(64)也是有講究的,具體設(shè)為多少這個沒有標準值,需要根據(jù)自身業(yè)務(wù)發(fā)展,數(shù)據(jù)增量進行預(yù)估。

根據(jù)我個人的經(jīng)驗來看,至少需要保證分好之后的小表在業(yè)務(wù)發(fā)展的幾年之內(nèi)都不會出現(xiàn)單表數(shù)據(jù)量過大(比如達到千萬級)。

我更傾向于在數(shù)據(jù)庫可接受的范圍內(nèi)盡可能的增大這個分表數(shù),畢竟如果后續(xù)小表也達到瓶頸需要再進行一次分表擴容,那是非常痛苦的。

目前筆者還沒經(jīng)歷這一步,所以本文沒有相關(guān)介紹。

但是這個數(shù)量又不是瞎選的,和 HashMap 一樣,也建議得是 2^n,這樣可以方便在擴容的時盡可能的少遷移數(shù)據(jù)。

Range + Hash

當然還有一種思路, Range 和 Hash 是否可以混用。

比如我們一開始采用的是 Hash 分表,但是數(shù)據(jù)增長巨大,導(dǎo)致每張分表數(shù)據(jù)很快達到瓶頸,這樣就不得不再做擴容,比如由 64 張表擴容到 256 張。

但擴容時想要做到不停機遷移數(shù)據(jù)非常困難,即便是停機,那停多久呢?也不好說。

所以我們是否可以在 Mod 分表的基礎(chǔ)上再分為月表,借助于 Range 自身的擴展性就不用考慮后續(xù)數(shù)據(jù)遷移的事情了。

 

這種方式理論可行,但我沒有實際用過,給大家的思路做個參考吧。

煩人的數(shù)據(jù)遷移

分表規(guī)則弄好后其實只是完成了分表的第一步,真正麻煩的是數(shù)據(jù)遷移,或者說是如何做到對業(yè)務(wù)影響最小的數(shù)據(jù)遷移。

除非是一開始就做了分表,所以數(shù)據(jù)遷移這一步驟肯定是跑不掉的。

下面整理下目前我們的做法供大家參考:

  1. 一旦分表上線后所有的數(shù)據(jù)寫入、查詢都是針對于分表的,所以原有大表內(nèi)的數(shù)據(jù)必須得遷移到分表里,不然對業(yè)務(wù)的影響極大。
  2. 我們估算了對一張 2 億左右的表進行遷移,自己寫的遷移程序,大概需要花 4~5 天的時間才能完成遷移。
  3. 意味著這段時間內(nèi),以前的數(shù)據(jù)對用戶是不可見的,顯然這樣業(yè)務(wù)不能接受。
  4. 于是我們做了一個兼容處理:分表改造上線后,所有新產(chǎn)生的數(shù)據(jù)寫入分表,但對歷史數(shù)據(jù)的操作還走老表,這樣就少了數(shù)據(jù)遷移這一步驟。
  5. 只是需要在操作數(shù)據(jù)之前做一次路由判斷,當新數(shù)據(jù)產(chǎn)生的足夠多時(我們是兩個月時間),幾乎所有的操作都是針對于分表,再從庫啟動數(shù)據(jù)遷移,數(shù)據(jù)遷移完畢后將原有的路由判斷去掉。
  6. 最后所有的數(shù)據(jù)都從分表產(chǎn)生和寫入。

至此整個分表操作完成。

 

業(yè)務(wù)兼容

同時分表之后還需要兼容其他業(yè)務(wù);比如原有的報表業(yè)務(wù)、分頁查詢等,現(xiàn)在來看看我們是如何處理的。

報表

首先是報表,沒分表之前之間查詢一張表就搞定了,現(xiàn)在不同,由一張表變?yōu)?N 張表。

所以原有的查詢要改為遍歷所有的分表,考慮到性能可以利用多線程并發(fā)查詢分表數(shù)據(jù)然后匯總。

不過只依靠 Java 來對這么大量的數(shù)據(jù)做統(tǒng)計分析還是不現(xiàn)實,剛開始可以應(yīng)付過去,后續(xù)還得用上大數(shù)據(jù)平臺來處理。

查詢

再一個是查詢,原有的分頁查詢肯定是不能用了,畢竟對上億的數(shù)據(jù)分頁其實沒什么意義。

只能提供通過分表字段的查詢,比如是按照訂單 ID 分表,那查詢條件就得帶上這個字段,不然就會涉及到遍歷所有表。

這也是所有分表之后都會遇到的一個問題,除非不用 MySQL 這類關(guān)系型數(shù)據(jù)庫。

分庫

分表完成后可以解決單表的壓力,但數(shù)據(jù)庫本身的壓力卻沒有下降。

我們在完成分表之后的一個月內(nèi)又由于數(shù)據(jù)庫里“其他表”的寫入導(dǎo)致整個數(shù)據(jù)庫 IO 增加,而且這些“其他表”還和業(yè)務(wù)關(guān)系不大。

也就是說一些可有可無的數(shù)據(jù)導(dǎo)致了整體業(yè)務(wù)受影響,這是非常不劃算的事情。

于是我們便把這幾張表單獨移到一個新的數(shù)據(jù)庫中,完全和現(xiàn)有的業(yè)務(wù)隔離開來。

這樣就會涉及到幾個改造:

  1. 應(yīng)用自身對這些數(shù)據(jù)的查詢、寫入都要改為調(diào)用一個獨立的 Dubbo 服務(wù),由這個服務(wù)對遷移的表進行操作。
  2. 暫時不做數(shù)據(jù)遷移,所以查詢時也得按照分表那樣做一個兼容,如果查詢老數(shù)據(jù)就要在當前庫查詢,新數(shù)據(jù)就要調(diào)用 Dubbo 接口進行查詢。
  3. 對這些表的一些關(guān)聯(lián)查詢也得改造為查詢 Dubbo 接口,在內(nèi)存中進行拼接即可。
  4. 如果數(shù)據(jù)量確實很大,也可將同步的 Dubbo 接口換為寫入消息隊列來提高吞吐量。

目前我們將這類數(shù)據(jù)量巨大但對業(yè)務(wù)不太影響的表單獨遷到一個庫后,數(shù)據(jù)庫的整體 IO 下降明顯,業(yè)務(wù)也恢復(fù)正常。

總結(jié)

最后我們還需要做一步歷史數(shù)據(jù)歸檔的操作,將 N 個月之前的數(shù)據(jù)要定期遷移到 HBASE 之類存儲,保證 MySQL 中的數(shù)據(jù)一直保持在一個可接受的范圍。

而歸檔數(shù)據(jù)的查詢便依賴于大數(shù)據(jù)提供服務(wù)。

本次分庫分表是一次非常難得的實踐操作,網(wǎng)上大部分的資料都是在汽車出廠前就換好了輪胎。

而我們大部分碰到的場景都是要對高速路上跑著的車子換胎,一不小心就“車毀人亡”。

責(zé)任編輯:武曉燕 來源: crossoverJie
相關(guān)推薦

2024-07-26 00:16:11

2020-07-30 17:59:34

分庫分表SQL數(shù)據(jù)庫

2021-05-08 18:50:57

分庫分表中間件

2019-01-29 15:25:11

阿里巴巴數(shù)據(jù)庫分庫分表

2021-08-31 20:21:11

VitessMySQL分庫

2023-08-11 08:59:49

分庫分表數(shù)據(jù)數(shù)據(jù)庫

2020-12-29 09:23:40

分庫分表訂單

2020-11-18 09:39:02

MySQL數(shù)據(jù)庫SQL

2019-08-07 14:52:34

分庫分表數(shù)據(jù)庫

2020-07-28 09:04:09

NewSQL分庫分表

2021-01-26 05:37:08

分庫分表內(nèi)存

2022-07-11 08:16:47

NewSQL關(guān)系數(shù)據(jù)庫系統(tǒng)

2025-04-01 08:45:00

2024-06-28 14:34:15

2019-01-16 14:00:54

數(shù)據(jù)庫分庫分表

2021-10-29 07:25:32

分庫分表技巧

2020-09-27 08:00:49

分庫分表

2024-08-07 10:34:46

2025-02-17 10:30:01

2024-08-02 15:47:28

數(shù)據(jù)庫分庫分表
點贊
收藏

51CTO技術(shù)棧公眾號