你好,歡迎進(jìn)入江蘇優(yōu)軟數(shù)字科技有限公司官網(wǎng)!
發(fā)布時(shí)間:2023-11-12
瀏覽次數(shù):0
大家好,我是頂級(jí)建筑師。
一、概述
順應(yīng)趨勢,大數(shù)據(jù)的高并發(fā)需要不斷的系統(tǒng)升級(jí),分庫分表就是其中之一。
2、為什么要分庫分表?
場景:隨著互聯(lián)網(wǎng)技術(shù)的蓬勃發(fā)展,大數(shù)據(jù)、高并發(fā)是很多企業(yè)遇到的情況。 例如,隨著公司業(yè)務(wù)的發(fā)展,系統(tǒng)用戶數(shù)量迅速增加。 系統(tǒng)每天會(huì)新增10萬條數(shù)據(jù),一個(gè)月會(huì)新增300萬條數(shù)據(jù)。 單表數(shù)據(jù)量已達(dá)到數(shù)百萬,高峰期請(qǐng)求數(shù)達(dá)到1000次。 處理的辦法是我們?cè)诰€部署幾臺(tái)機(jī)器,使用nginx做負(fù)載均衡,數(shù)據(jù)庫支持足夠。 然而,數(shù)據(jù)量不斷增長,下一步我們?cè)撛趺崔k?
當(dāng)每天有幾千萬的活躍用戶,單表每天新增數(shù)據(jù)多達(dá)50萬條時(shí),一張表的總數(shù)據(jù)量就達(dá)到了20~3000萬。 數(shù)據(jù)庫磁盤容量不斷被消耗,并發(fā)峰值達(dá)到驚人的5000。 ~! 此時(shí),單一數(shù)據(jù)庫已經(jīng)無法抵抗。
3、分表3.1、分表計(jì)劃
當(dāng)單表達(dá)到千萬級(jí)時(shí),單表數(shù)據(jù)量過大,會(huì)極大影響SQL執(zhí)行的性能。 稍后,你的 SQL 可能會(huì)運(yùn)行得很慢。 一般來說,當(dāng)單表達(dá)到幾百萬的時(shí)候,性能會(huì)比較差,就會(huì)出現(xiàn)分表的情況。
對(duì)數(shù)值取模
使用Id取模的方法來劃分表格。 例如表示例中,表根據(jù)cusno字段分為4個(gè)庫。 余數(shù)為0的放入第一庫,余數(shù)為1的放入第二庫,余數(shù)為2的放入第三庫。 ,余數(shù)為3的放入第三庫。 這樣,同一個(gè)用戶的數(shù)據(jù)就會(huì)分散到不同的表中。 如果查詢條件包含cusno字段,則可以明確定位對(duì)應(yīng)的表進(jìn)行查詢。
示例描述:
// 首先創(chuàng)建三個(gè)表,然后我創(chuàng)建一個(gè)uuid表,用于提供自增id。
create?table?**customer0**(
????id?int?unsigned?primary?key?,
????name?varchar(32)?not?null?default?'',
????pwd?varchar(32)?not?null?default?''
)engine=myisam?charset?utf8;
create?table?**customer1**(
????id?int?unsigned?primary?key?,
????name?varchar(32)?not?null?default?'',
????pwd?varchar(32)?not?null?default?''
)engine=myisam?charset?utf8;
create?table?**customer2**(
????id?int?unsigned?primary?key?,
????name?varchar(32)?not?null?default?'',
????pwd?varchar(32)?not?null?default?''
)engine=myisam?charset?utf8;
create?table?**customer3**(
????id?int?unsigned?primary?key?,
????name?varchar(32)?not?null?default?'',
????pwd?varchar(32)?not?null?default?''
)engine=myisam?charset?utf8;
create?table?**uuid**(
????id?int?unsigned?primary?key?auto_increment
)engine=myisam?charset?utf8;
**利用以上創(chuàng)建的表進(jìn)行業(yè)務(wù)處理**
@Service
public?class?CustomerService?{
????@Autowired
?????private?JdbcTemplate?jdbcTemplate;
????/**
?????*?注冊(cè)的代碼
?????*?@param?name
?????*?@param?pwd
?????*?@return
?????*/
????public?String?regiter(String?name,String?pwd){
????????//1.生成cusno?,-??先獲取到?自定增長ID
????????String?insertUUidSql?=?"insert?into?uuid?values(null)";//插入空數(shù)據(jù),這里的id是自動(dòng)增長的
????????jdbcTemplate.update(insertUUidSql);//執(zhí)行
??????????//查詢到最近的添加的主鍵id
????????Long?cusno?=?jdbcTemplate.queryForObject("select?last_insert_id()",?Long.class);
????????//2.存放具體的那張表中?-?也就是判斷存儲(chǔ)表名稱
????????String?tableName?=?"customer"?+?cusno?%?3;
????????//3.插入到具體的表中去-?注冊(cè)數(shù)據(jù)
????????String?insertUserSql?=?"INSERT?INTO?"?+?tableName?+?"?VALUES?('"?+?cusno?+?"','"?+?name?+?"','"?+?pwd?+?"');";
????????System.out.println("insertUserSql:"?+?insertUserSql);
????????jdbcTemplate.update(insertUserSql);
????????return?"success";
????}
???/**
?????*?通過cusno查詢name
?????*?@param?userid
?????*?@return
?????*/
????public?String?get(Long?cusno)?{
????????//具體哪張表
????????String?tableName?=?"customer"?+?cusno?%?3;
????????String?sql?=?"select?name?from?"?+?tableName?+?"?where?id="+cusno;
????????System.out.println("SQL:"?+?sql);
????????return?jdbcTemplate.queryForObject(sql,?String.class);//執(zhí)行查詢出name
????}
}
優(yōu)缺點(diǎn)總結(jié)
優(yōu)勢:
將一張數(shù)據(jù)表的數(shù)據(jù)劃分為多張表后,數(shù)據(jù)會(huì)比較均勻,這樣會(huì)減少高并發(fā)訪問對(duì)數(shù)據(jù)庫造成的壓力。
缺點(diǎn):
如果后期擴(kuò)容,則需要遷移舊數(shù)據(jù)并重新計(jì)算。
跨表查詢的復(fù)雜度增加。 例如上例中,如果經(jīng)常使用的查詢條件中不包含cusno,則不會(huì)定位到數(shù)據(jù)庫。 因此,需要同時(shí)向四個(gè)庫發(fā)起查詢,然后合并內(nèi)存中的數(shù)據(jù),取最小集合返回給應(yīng)用程序。 相反,圖書館成了一個(gè)累贅。
根據(jù)數(shù)值范圍
為了解決后期集群擴(kuò)容時(shí)遷移舊數(shù)據(jù)的問題,可以使用按日期或ID進(jìn)行表分區(qū)。 例如:將不同月份甚至幾天的數(shù)據(jù)按日期分布到不同的表中; 將 從 1 到 9999 的記錄分配給第一個(gè)表,將 10000 到 20000 的記錄分配給第二個(gè)表,依此類推。 從某種意義上說,一些系統(tǒng)中采用的“冷熱數(shù)據(jù)分離”,將一些較少使用的歷史數(shù)據(jù)遷移到其他庫,只在業(yè)務(wù)功能中提供熱數(shù)據(jù)查詢,也是類似的做法。
的優(yōu)點(diǎn)和缺點(diǎn)
優(yōu)勢:
單臺(tái)尺寸可控
橫向擴(kuò)展自然很容易。 如果后續(xù)想要擴(kuò)展整個(gè)分片集群,只需要添加節(jié)點(diǎn)即可,不需要遷移其他分片的數(shù)據(jù)。
使用分片字段進(jìn)行范圍搜索時(shí),連續(xù)分片可以快速定位分片進(jìn)行快速查詢,有效避免跨分片查詢問題。
缺點(diǎn):
熱數(shù)據(jù)成為性能瓶頸。 連續(xù)分片可能存在數(shù)據(jù)熱點(diǎn),例如按時(shí)間字段分片。 有些分片存儲(chǔ)的是最近一段時(shí)間的數(shù)據(jù),可能被頻繁讀寫,而有些分片存儲(chǔ)的是很少被查詢的歷史數(shù)據(jù)。
4. 分庫
即一個(gè)數(shù)據(jù)庫一般最多可以支持2000個(gè)并發(fā)。 隨著查詢量的增加,單個(gè)數(shù)據(jù)庫服務(wù)器已經(jīng)無法支持。 此外,為了獲得健康的單數(shù)據(jù)庫并發(fā)值,最好保持在每秒 1000 個(gè)左右。 不要太大,否則會(huì)引起問題。 導(dǎo)致單個(gè)DB的存儲(chǔ)空間不足。 然后就可以將一個(gè)庫的數(shù)據(jù)拆分成多個(gè)庫,訪問時(shí)訪問一個(gè)庫。
垂直分割
垂直拆分就是對(duì)數(shù)據(jù)庫的列進(jìn)行處理,列與對(duì)應(yīng)的業(yè)務(wù)相關(guān)。 這意味著相關(guān)性較低的不同表根據(jù)業(yè)務(wù)耦合存儲(chǔ)在不同的數(shù)據(jù)庫中。 另外,搜索公眾號(hào)Linux,了解如何在后臺(tái)回復(fù)“git books”,即可獲得驚喜大禮包。
考慮到微服務(wù),該方法類似于將一個(gè)大系統(tǒng)拆分為多個(gè)小系統(tǒng)。 它們按照業(yè)務(wù)分類獨(dú)立劃分,每個(gè)微服務(wù)使用獨(dú)立的數(shù)據(jù)庫。 例如,最初有一個(gè)包含用戶表的數(shù)據(jù)庫。 隨著公司業(yè)務(wù)的發(fā)展,技術(shù)團(tuán)隊(duì)成員也隨之?dāng)U大,分為不同的技術(shù)組,不同的組負(fù)責(zé)不同的業(yè)務(wù)模塊。比如A團(tuán)隊(duì)負(fù)責(zé)用戶模塊,B團(tuán)隊(duì)負(fù)責(zé)產(chǎn)品模塊,分為庫和庫。
需要解決的問題:跨庫事務(wù)、jion查詢等。
水平分割
按照規(guī)則,一般是水平分庫在垂直分庫之后。 例如,每天處理的訂單量是海量的,可以按照一定的規(guī)則和級(jí)別進(jìn)行劃分。 例如,表太大,無法存儲(chǔ)在單個(gè)數(shù)據(jù)庫中,或者訪問性能受到壓力。 將一個(gè)表拆分為多個(gè)表,每個(gè)表存儲(chǔ)部分記錄并保存在不同的數(shù)據(jù)庫中。 水平拆分需要對(duì)系統(tǒng)進(jìn)行重大改變。 。
1)縱向擴(kuò)展,升級(jí)數(shù)據(jù)庫所在物理機(jī),提高內(nèi)存/存儲(chǔ)/IO性能。 但這種升級(jí)成本高昂,且只能滿足短期需求。
2)橫向擴(kuò)展,將訂單庫拆分為多個(gè)庫,分發(fā)到多臺(tái)機(jī)器上存儲(chǔ)和訪問。 這種方式支持橫向擴(kuò)展,可以滿足長期需求。
訂單數(shù)據(jù)庫主要包括訂單主表/訂單明細(xì)表(記錄產(chǎn)品詳細(xì)信息)/訂單擴(kuò)展表。 水平分庫將這三個(gè)表的記錄劃分到多個(gè)數(shù)據(jù)庫中。 訂單橫向分庫效果如下圖:
數(shù)據(jù)庫分片策略:類似于水平分表
分庫維度確定后,如何將記錄劃分到各個(gè)數(shù)據(jù)庫中? 一般有兩種方式:
根據(jù)取值范圍,例如將用戶ID為1-9999的記錄分配給第一庫,將用戶ID為10000-20000的記錄分配給第二庫,以此類推。
根據(jù)取模值intellij idea 數(shù)據(jù)庫關(guān)系圖,例如用戶ID mod n,余數(shù)為0的記錄放入第一個(gè)庫,余數(shù)為1的記錄放入第二個(gè)庫,以此類推。
需要解決的問題:數(shù)據(jù)路由、組裝。
讀寫分離
對(duì)于時(shí)間不敏感的數(shù)據(jù),可以通過讀寫分離的方式緩解數(shù)據(jù)庫壓力。
需要解決的問題:區(qū)分允許一定時(shí)間延遲的業(yè)務(wù)、數(shù)據(jù)同步問題。
垂直分庫-->水平分庫-->讀寫分離
五、分裂后面臨的新問題的解決辦法
常用解決方案:站在巨人的肩膀上可以省很多力氣。 目前,已經(jīng)有一些相對(duì)成熟的分庫分表開源解決方案。 擴(kuò)展:
使用第三方數(shù)據(jù)庫中間件(Atlas、Mycat、TDDL、DRDS),業(yè)務(wù)系統(tǒng)需要配合數(shù)據(jù)存儲(chǔ)的升級(jí)。 綜合考慮后,其實(shí)建議考慮-jdbc和Mycatintellij idea 數(shù)據(jù)庫關(guān)系圖,這兩個(gè)都可以考慮使用。
-jdbc 這一層方案的優(yōu)點(diǎn)是不需要部署,運(yùn)維成本低,不需要代理層二次轉(zhuǎn)發(fā)請(qǐng)求,性能較高。 不過如果有升級(jí)什么的,每個(gè)系統(tǒng)都需要重新升級(jí)版本才發(fā)布。 每個(gè)系統(tǒng)都需要-jdbc依賴;
Mycat的代理層方案的缺點(diǎn)是需要自己部署和運(yùn)維一套中間件,運(yùn)維成本較高。 但好處是對(duì)每個(gè)項(xiàng)目都是透明的。 如果遇到升級(jí)之類的,通過自己的中間件來處理即可。 。
一般來說,兩種方案都可以使用,但我個(gè)人建議中小型公司選擇-jdbc。 該層解決方案重量輕,維護(hù)成本低。 不需要額外的人力,中小型公司的系統(tǒng)復(fù)雜度會(huì)更低。 ,項(xiàng)目不多; 不過中大型公司最好選擇Mycat之類的代理層解決方案,因?yàn)榇蠊究赡芟到y(tǒng)和項(xiàng)目很多,團(tuán)隊(duì)很大,人員充足,所以最好有專門的人來研究和維護(hù)他們。 mycat,然后大量的項(xiàng)目就可以直接透明的使用了。
隨附的:
負(fù)載均衡:車輛超載,多車運(yùn)輸物料。 有一個(gè)總調(diào)度中心分配每輛車的重量和拉動(dòng)的貨物量。 系統(tǒng)中,總調(diào)度中心可以是nginx。 通過配置多臺(tái)服務(wù)器的IP地址,進(jìn)行權(quán)重分配,并采用輪詢算法實(shí)現(xiàn)處理大并發(fā)的策略。
主鍵生成策略:
歡迎大家互相討論、碰撞、發(fā)表意見。 如果有什么問題也可以和我交流。
最后,我們整理了一份BAT各大公司的真實(shí)面試題清單,供讀者參考。 如果您需要,可以掃描二維碼并回復(fù)“面試問題”即可獲取。
公眾號(hào)后臺(tái)回復(fù)結(jié)構(gòu)或結(jié)構(gòu)整齊有驚喜大禮包!
頂尖建筑師交流群
《頂尖建筑師》專門為讀者和建筑師建立了交流群。 可以添加小編微信進(jìn)群。 歡迎有想法、愿意分享的朋友一起交流學(xué)習(xí)。
掃一掃添加好友邀請(qǐng)您加入建筑師群。 添加我時(shí)請(qǐng)注明【姓名+公司+職位】
如有侵權(quán)請(qǐng)聯(lián)系刪除!
Copyright ? 2023 江蘇優(yōu)軟數(shù)字科技有限公司 All Rights Reserved.正版sublime text、Codejock、IntelliJ IDEA、sketch、Mestrenova、DNAstar服務(wù)提供商
13262879759
微信二維碼