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

MySQL分庫(kù)分表會(huì)帶來(lái)哪些問(wèn)題?

數(shù)據(jù)庫(kù) MySQL
分庫(kù)分表能有效的環(huán)節(jié)單機(jī)和單庫(kù)帶來(lái)的性能瓶頸和壓力,突破網(wǎng)絡(luò)IO、硬件資源、連接數(shù)的瓶頸,同時(shí)也帶來(lái)了一些問(wèn)題。下面將描述這些技術(shù)挑戰(zhàn)以及對(duì)應(yīng)的解決思路。

分庫(kù)分表能有效的環(huán)節(jié)單機(jī)和單庫(kù)帶來(lái)的性能瓶頸和壓力,突破網(wǎng)絡(luò)IO、硬件資源、連接數(shù)的瓶頸,同時(shí)也帶來(lái)了一些問(wèn)題。下面將描述這些技術(shù)挑戰(zhàn)以及對(duì)應(yīng)的解決思路。

[[272325]]

1、事務(wù)一致性問(wèn)題

分布式事務(wù)

當(dāng)更新內(nèi)容同時(shí)分布在不同庫(kù)中,不可避免會(huì)帶來(lái)跨庫(kù)事務(wù)問(wèn)題??绶制聞?wù)也是分布式事務(wù),沒(méi)有簡(jiǎn)單的方案,一般可使用"XA協(xié)議"和"兩階段提交"處理。

分布式事務(wù)能最大限度保證了數(shù)據(jù)庫(kù)操作的原子性。但在提交事務(wù)時(shí)需要協(xié)調(diào)多個(gè)節(jié)點(diǎn),推后了提交事務(wù)的時(shí)間點(diǎn),延長(zhǎng)了事務(wù)的執(zhí)行時(shí)間。導(dǎo)致事務(wù)在訪問(wèn)共享資源時(shí)發(fā)生沖突或死鎖的概率增高。隨著數(shù)據(jù)庫(kù)節(jié)點(diǎn)的增多,這種趨勢(shì)會(huì)越來(lái)越嚴(yán)重,從而成為系統(tǒng)在數(shù)據(jù)庫(kù)層面上水平擴(kuò)展的枷鎖。

最終一致性

對(duì)于那些性能要求很高,但對(duì)一致性要求不高的系統(tǒng),往往不苛求系統(tǒng)的實(shí)時(shí)一致性,只要在允許的時(shí)間段內(nèi)達(dá)到最終一致性即可,可采用事務(wù)補(bǔ)償?shù)姆绞健Ec事務(wù)在執(zhí)行中發(fā)生錯(cuò)誤后立即回滾的方式不同,事務(wù)補(bǔ)償是一種事后檢查補(bǔ)救的措施,一些常見(jiàn)的實(shí)現(xiàn)方法有:對(duì)數(shù)據(jù)進(jìn)行對(duì)賬檢查,基于日志進(jìn)行對(duì)比,定期同標(biāo)準(zhǔn)數(shù)據(jù)來(lái)源進(jìn)行同步等等。事務(wù)補(bǔ)償還要結(jié)合業(yè)務(wù)系統(tǒng)來(lái)考慮。

2、跨節(jié)點(diǎn)關(guān)聯(lián)查詢 join 問(wèn)題

切分之前,系統(tǒng)中很多列表和詳情頁(yè)所需的數(shù)據(jù)可以通過(guò)sql join來(lái)完成。而切分之后,數(shù)據(jù)可能分布在不同的節(jié)點(diǎn)上,此時(shí)join帶來(lái)的問(wèn)題就比較麻煩了,考慮到性能,盡量避免使用join查詢。

跨節(jié)點(diǎn)關(guān)聯(lián)查詢 join 問(wèn)題

切分之前,系統(tǒng)中很多列表和詳情頁(yè)所需的數(shù)據(jù)可以通過(guò)sql join來(lái)完成。而切分之后,數(shù)據(jù)可能分布在不同的節(jié)點(diǎn)上,此時(shí)join帶來(lái)的問(wèn)題就比較麻煩了,考慮到性能,盡量避免使用join查詢。

解決這個(gè)問(wèn)題的一些方法:

1)全局表

全局表,也可看做是"數(shù)據(jù)字典表",就是系統(tǒng)中所有模塊都可能依賴的一些表,為了避免跨庫(kù)join查詢,可以將這類(lèi)表在每個(gè)數(shù)據(jù)庫(kù)中都保存一份。這些數(shù)據(jù)通常很少會(huì)進(jìn)行修改,所以也不擔(dān)心一致性的問(wèn)題。

2)字段冗余

一種典型的反范式設(shè)計(jì),利用空間換時(shí)間,為了性能而避免join查詢。例如:訂單表保存userId時(shí)候,也將userName冗余保存一份,這樣查詢訂單詳情時(shí)就不需要再去查詢"買(mǎi)家user表"了。

但這種方法適用場(chǎng)景也有限,比較適用于依賴字段比較少的情況。而冗余字段的數(shù)據(jù)一致性也較難保證,就像上面訂單表的例子,買(mǎi)家修改了userName后,是否需要在歷史訂單中同步更新呢?這也要結(jié)合實(shí)際業(yè)務(wù)場(chǎng)景進(jìn)行考慮。

3)數(shù)據(jù)組裝

在系統(tǒng)層面,分兩次查詢,第一次查詢的結(jié)果集中找出關(guān)聯(lián)數(shù)據(jù)id,然后根據(jù)id發(fā)起第二次請(qǐng)求得到關(guān)聯(lián)數(shù)據(jù)。最后將獲得到的數(shù)據(jù)進(jìn)行字段拼裝。

4)ER分片

關(guān)系型數(shù)據(jù)庫(kù)中,如果可以先確定表之間的關(guān)聯(lián)關(guān)系,并將那些存在關(guān)聯(lián)關(guān)系的表記錄存放在同一個(gè)分片上,那么就能較好的避免跨分片join問(wèn)題。在1:1或1:n的情況下,通常按照主表的ID主鍵切分。如下圖所示:

Mysql數(shù)據(jù)庫(kù)-分庫(kù)分表都帶來(lái)的哪些問(wèn)題?

這樣一來(lái),Data Node1上面的order訂單表與orderdetail訂單詳情表就可以通過(guò)orderId進(jìn)行局部的關(guān)聯(lián)查詢了,Data Node2上也一樣。

3、跨節(jié)點(diǎn)分頁(yè)、排序、函數(shù)問(wèn)題

跨節(jié)點(diǎn)多庫(kù)進(jìn)行查詢時(shí),會(huì)出現(xiàn)limit分頁(yè)、order by排序等問(wèn)題。分頁(yè)需要按照指定字段進(jìn)行排序,當(dāng)排序字段就是分片字段時(shí),通過(guò)分片規(guī)則就比較容易定位到指定的分片;當(dāng)排序字段非分片字段時(shí),就變得比較復(fù)雜了。需要先在不同的分片節(jié)點(diǎn)中將數(shù)據(jù)進(jìn)行排序并返回,然后將不同分片返回的結(jié)果集進(jìn)行匯總和再次排序,最終返回給用戶。如圖所示:

Mysql數(shù)據(jù)庫(kù)-分庫(kù)分表都帶來(lái)的哪些問(wèn)題?

上圖中只是取第一頁(yè)的數(shù)據(jù),對(duì)性能影響還不是很大。但是如果取得頁(yè)數(shù)很大,情況則變得復(fù)雜很多,因?yàn)楦鞣制?jié)點(diǎn)中的數(shù)據(jù)可能是隨機(jī)的,為了排序的準(zhǔn)確性,需要將所有節(jié)點(diǎn)的前N頁(yè)數(shù)據(jù)都排序好做合并,最后再進(jìn)行整體的排序,這樣的操作時(shí)很耗費(fèi)CPU和內(nèi)存資源的,所以頁(yè)數(shù)越大,系統(tǒng)的性能也會(huì)越差。

在使用Max、Min、Sum、Count之類(lèi)的函數(shù)進(jìn)行計(jì)算的時(shí)候,也需要先在每個(gè)分片上執(zhí)行相應(yīng)的函數(shù),然后將各個(gè)分片的結(jié)果集進(jìn)行匯總和再次計(jì)算,最終將結(jié)果返回。如圖所示:

Mysql數(shù)據(jù)庫(kù)-分庫(kù)分表都帶來(lái)的哪些問(wèn)題?

4、全局主鍵避重問(wèn)題

在分庫(kù)分表環(huán)境中,由于表中數(shù)據(jù)同時(shí)存在不同數(shù)據(jù)庫(kù)中,主鍵值平時(shí)使用的自增長(zhǎng)將無(wú)用武之地,某個(gè)分區(qū)數(shù)據(jù)庫(kù)自生成的ID無(wú)法保證全局唯一。因此需要單獨(dú)設(shè)計(jì)全局主鍵,以避免跨庫(kù)主鍵重復(fù)問(wèn)題。有一些常見(jiàn)的主鍵生成策略:

1)UUID

UUID標(biāo)準(zhǔn)形式包含32個(gè)16進(jìn)制數(shù)字,分為5段,形式為8-4-4-4-12的36個(gè)字符,例如:550e8400-e29b-41d4-a716-446655440000

UUID是主鍵是最簡(jiǎn)單的方案,本地生成,性能高,沒(méi)有網(wǎng)絡(luò)耗時(shí)。但缺點(diǎn)也很明顯,由于UUID非常長(zhǎng),會(huì)占用大量的存儲(chǔ)空間;另外,作為主鍵建立索引和基于索引進(jìn)行查詢時(shí)都會(huì)存在性能問(wèn)題,在InnoDB下,UUID的無(wú)序性會(huì)引起數(shù)據(jù)位置頻繁變動(dòng),導(dǎo)致分頁(yè)。

2)結(jié)合數(shù)據(jù)庫(kù)維護(hù)主鍵ID表

在數(shù)據(jù)庫(kù)中建立 sequence 表:

  1. CREATE TABLE `sequence` (  
  2.  `id` bigint(20) unsigned NOT NULL auto_increment,  
  3.  `stub` char(1) NOT NULL default '',  
  4.  PRIMARY KEY (`id`),  
  5.  UNIQUE KEY `stub` (`stub`)  
  6. ) ENGINE=MyISAM; 

stub字段設(shè)置為唯一索引,同一stub值在sequence表中只有一條記錄,可以同時(shí)為多張表生成全局ID。sequence表的內(nèi)容,如下所示:

  1. +-------------------+------+  
  2. | id | stub |  
  3. +-------------------+------+  
  4. | 72157623227190423 | a |  
  5. +-------------------+------+  

使用 MyISAM 存儲(chǔ)引擎而不是 InnoDB,以獲取更高的性能。MyISAM使用的是表級(jí)別的鎖,對(duì)表的讀寫(xiě)是串行的,所以不用擔(dān)心在并發(fā)時(shí)兩次讀取同一個(gè)ID值。

當(dāng)需要全局唯一的64位ID時(shí),執(zhí)行:

  1. REPLACE INTO sequence (stub) VALUES ('a');  
  2. SELECT LAST_INSERT_ID();  

這兩條語(yǔ)句是Connection級(jí)別的,select last_insert_id() 必須與 replace into 在同一數(shù)據(jù)庫(kù)連接下才能得到剛剛插入的新ID。

使用replace into代替insert into好處是避免了表行數(shù)過(guò)大,不需要另外定期清理。

此方案較為簡(jiǎn)單,但缺點(diǎn)也明顯:存在單點(diǎn)問(wèn)題,強(qiáng)依賴DB,當(dāng)DB異常時(shí),整個(gè)系統(tǒng)都不可用。配置主從可以增加可用性,但當(dāng)主庫(kù)掛了,主從切換時(shí),數(shù)據(jù)一致性在特殊情況下難以保證。另外性能瓶頸限制在單臺(tái)MySQL的讀寫(xiě)性能。

flickr團(tuán)隊(duì)使用的一種主鍵生成策略,與上面的sequence表方案類(lèi)似,但更好的解決了單點(diǎn)和性能瓶頸的問(wèn)題。

這一方案的整體思想是:建立2個(gè)以上的全局ID生成的服務(wù)器,每個(gè)服務(wù)器上只部署一個(gè)數(shù)據(jù)庫(kù),每個(gè)庫(kù)有一張sequence表用于記錄當(dāng)前全局ID。表中ID增長(zhǎng)的步長(zhǎng)是庫(kù)的數(shù)量,起始值依次錯(cuò)開(kāi),這樣能將ID的生成散列到各個(gè)數(shù)據(jù)庫(kù)上。如下圖所示:

Mysql數(shù)據(jù)庫(kù)-分庫(kù)分表都帶來(lái)的哪些問(wèn)題?

由兩個(gè)數(shù)據(jù)庫(kù)服務(wù)器生成ID,設(shè)置不同的auto_increment值。第一臺(tái)sequence的起始值為1,每次步長(zhǎng)增長(zhǎng)2,另一臺(tái)的sequence起始值為2,每次步長(zhǎng)增長(zhǎng)也是2。結(jié)果第一臺(tái)生成的ID都是奇數(shù)(1, 3, 5, 7 ...),第二臺(tái)生成的ID都是偶數(shù)(2, 4, 6, 8 ...)。

這種方案將生成ID的壓力均勻分布在兩臺(tái)機(jī)器上。同時(shí)提供了系統(tǒng)容錯(cuò),第一臺(tái)出現(xiàn)了錯(cuò)誤,可以自動(dòng)切換到第二臺(tái)機(jī)器上獲取ID。但有以下幾個(gè)缺點(diǎn):系統(tǒng)添加機(jī)器,水平擴(kuò)展時(shí)較復(fù)雜;每次獲取ID都要讀寫(xiě)一次DB,DB的壓力還是很大,只能靠堆機(jī)器來(lái)提升性能。

可以基于flickr的方案繼續(xù)優(yōu)化,使用批量的方式降低數(shù)據(jù)庫(kù)的寫(xiě)壓力,每次獲取一段區(qū)間的ID號(hào)段,用完之后再去數(shù)據(jù)庫(kù)獲取,可以大大減輕數(shù)據(jù)庫(kù)的壓力。如下圖所示:

Mysql數(shù)據(jù)庫(kù)-分庫(kù)分表都帶來(lái)的哪些問(wèn)題?

還是使用兩臺(tái)DB保證可用性,數(shù)據(jù)庫(kù)中只存儲(chǔ)當(dāng)前的最大ID。ID生成服務(wù)每次批量拉取6個(gè)ID,先將max_id修改為5,當(dāng)應(yīng)用訪問(wèn)ID生成服務(wù)時(shí),就不需要訪問(wèn)數(shù)據(jù)庫(kù),從號(hào)段緩存中依次派發(fā)0~5的ID。當(dāng)這些ID發(fā)完后,再將max_id修改為11,下次就能派發(fā)6~11的ID。于是,數(shù)據(jù)庫(kù)的壓力降低為原來(lái)的1/6。

3)Snowflake分布式自增ID算法

Twitter的snowflake算法解決了分布式系統(tǒng)生成全局ID的需求,生成64位的Long型數(shù)字,組成部分:

  • 第一位未使用
  • 接下來(lái)41位是毫秒級(jí)時(shí)間,41位的長(zhǎng)度可以表示69年的時(shí)間
  • 5位datacenterId,5位workerId。10位的長(zhǎng)度最多支持部署1024個(gè)節(jié)點(diǎn)
  • 最后12位是毫秒內(nèi)的計(jì)數(shù),12位的計(jì)數(shù)順序號(hào)支持每個(gè)節(jié)點(diǎn)每毫秒產(chǎn)生4096個(gè)ID序列
Mysql數(shù)據(jù)庫(kù)-分庫(kù)分表都帶來(lái)的哪些問(wèn)題?

這樣的好處是:毫秒數(shù)在高位,生成的ID整體上按時(shí)間趨勢(shì)遞增;不依賴第三方系統(tǒng),穩(wěn)定性和效率較高,理論上QPS約為409.6w/s(1000*2^12),并且整個(gè)分布式系統(tǒng)內(nèi)不會(huì)產(chǎn)生ID碰撞;可根據(jù)自身業(yè)務(wù)靈活分配bit位。

不足就在于:強(qiáng)依賴機(jī)器時(shí)鐘,如果時(shí)鐘回?fù)埽瑒t可能導(dǎo)致生成ID重復(fù)。

綜上

結(jié)合數(shù)據(jù)庫(kù)和snowflake的唯一ID方案,可以參考業(yè)界較為成熟的解法:Leaf——美團(tuán)點(diǎn)評(píng)分布式ID生成系統(tǒng),并考慮到了高可用、容災(zāi)、分布式下時(shí)鐘等問(wèn)題。

5、數(shù)據(jù)遷移、擴(kuò)容問(wèn)題

當(dāng)業(yè)務(wù)高速發(fā)展,面臨性能和存儲(chǔ)的瓶頸時(shí),才會(huì)考慮分片設(shè)計(jì),此時(shí)就不可避免的需要考慮歷史數(shù)據(jù)遷移的問(wèn)題。一般做法是先讀出歷史數(shù)據(jù),然后按指定的分片規(guī)則再將數(shù)據(jù)寫(xiě)入到各個(gè)分片節(jié)點(diǎn)中。此外還需要根據(jù)當(dāng)前的數(shù)據(jù)量和QPS,以及業(yè)務(wù)發(fā)展的速度,進(jìn)行容量規(guī)劃,推算出大概需要多少分片(一般建議單個(gè)分片上的單表數(shù)據(jù)量不超過(guò)1000W)

如果采用數(shù)值范圍分片,只需要添加節(jié)點(diǎn)就可以進(jìn)行擴(kuò)容了,不需要對(duì)分片數(shù)據(jù)遷移。如果采用的是數(shù)值取模分片,則考慮后期的擴(kuò)容問(wèn)題就相對(duì)比較麻煩。

責(zé)任編輯:華軒 來(lái)源: 今日頭條
相關(guān)推薦

2022-05-25 08:06:37

MySQL分庫(kù)分表

2025-03-03 12:30:00

import *代碼開(kāi)發(fā)

2025-01-07 08:20:49

2021-10-29 07:25:32

分庫(kù)分表技巧

2022-10-11 17:51:49

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

2020-11-18 09:39:02

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

2024-02-21 12:17:00

2020-07-30 17:59:34

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

2025-05-15 09:45:54

2018-09-21 15:50:58

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

2019-11-12 09:54:20

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

2020-01-07 09:40:25

數(shù)據(jù)庫(kù)MySQLRedis

2019-05-13 15:00:14

MySQLMyCat數(shù)據(jù)庫(kù)

2021-08-31 20:21:11

VitessMySQL分庫(kù)

2023-08-11 08:59:49

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

2023-09-26 00:45:11

MySQL拆表分片

2021-03-17 16:15:55

數(shù)據(jù)MySQL 架構(gòu)

2022-07-11 08:16:47

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

2020-07-28 09:04:09

NewSQL分庫(kù)分表

2021-01-26 05:37:08

分庫(kù)分表內(nèi)存
點(diǎn)贊
收藏

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