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

MySQL:如何保證雙十一的主備數(shù)據(jù)同步

數(shù)據(jù)庫(kù) MySQL
MySQL 5.7.22 的并行復(fù)制策略在通用性上還是有保證的。當(dāng)然,對(duì)于“表上沒(méi)主鍵”和“外鍵約束”的場(chǎng)景,WRITESET 策略也是沒(méi)法并行的,也會(huì)暫時(shí)退化為單線程模型。?

之前的文章我們提到過(guò),主備數(shù)據(jù)庫(kù)是通過(guò)binlog實(shí)現(xiàn)的數(shù)據(jù)同步:

主庫(kù)在接到客戶端更新請(qǐng)求時(shí),執(zhí)行內(nèi)部事務(wù)的更新邏輯,同時(shí)寫(xiě)binlog。 r

1)edo log commit后,才會(huì)回復(fù)客戶端ack; 

2)binlog寫(xiě)成功后就可以同步備庫(kù),因?yàn)閎inlog寫(xiě)盤(pán)成功后,就算后續(xù)commit失敗,數(shù)據(jù)庫(kù)也可以根據(jù)redo log+binlog重新恢復(fù)commit狀態(tài); 

備庫(kù)與主庫(kù)之間維護(hù)一個(gè)長(zhǎng)鏈接,有專(zhuān)門(mén)的線程來(lái)發(fā)送或者接收請(qǐng)求。

果凍布丁兔,公眾號(hào):陸隊(duì)長(zhǎng)MySQL:為什么所有實(shí)例可以保證數(shù)據(jù)一致性

無(wú)論是主備還是主從,實(shí)際上都是為了保證MySQL集群的高可用性:

無(wú)論是主備還是主從架構(gòu),實(shí)際上就是為了系統(tǒng)的高可用性實(shí)現(xiàn)的一個(gè)策略,防止主機(jī)因?yàn)槟承┕收蠈?dǎo)致異常下線,這時(shí)候備份或者從實(shí)例就會(huì)通過(guò)選擇或者其他策略成為主服務(wù)實(shí)例,對(duì)外繼續(xù)提供服務(wù)。

果凍布丁兔,公眾號(hào):陸隊(duì)長(zhǎng)MySQL:從MySQL看主從架構(gòu)高可用性實(shí)現(xiàn)

但是如果在一個(gè)壓力持續(xù)比較久(比如雙十一或者大促期間)的主從系統(tǒng)內(nèi),主服務(wù)器需要應(yīng)對(duì)龐大的數(shù)據(jù)讀寫(xiě)壓力,如果備庫(kù)執(zhí)行日志的速度低于主庫(kù)生成日志的速度,那么主從的主備延遲時(shí)間越來(lái)越長(zhǎng),導(dǎo)致備庫(kù)可能一直無(wú)法追上主庫(kù)。這時(shí)候就需要本節(jié)引入的備庫(kù)并行復(fù)制能力。

圖片圖片

如圖所示的兩個(gè)黑色箭頭是我們比較關(guān)注的,一個(gè)是客戶端寫(xiě)入主庫(kù),一個(gè)是備庫(kù)上sql_thread執(zhí)行中轉(zhuǎn)日志(relay log)。

主庫(kù)上影響并發(fā)主要是各種鎖,在備庫(kù)上的執(zhí)行,如果 從sql_thread更新數(shù)據(jù)使用單線程就很大可能導(dǎo)致主備延遲,這也是MySQL5.6版本前在主庫(kù)并發(fā)高或者TPS高時(shí)導(dǎo)致嚴(yán)重主備延遲問(wèn)題的原因。

圖片圖片

上圖有些類(lèi)似netty的線程模型,沒(méi)錯(cuò),如果是好的技術(shù)模型,那么在很多的技術(shù)棧中都會(huì)使用。

coordinator只負(fù)責(zé)讀取中轉(zhuǎn)日志和分發(fā)事務(wù),真正更新日志的邏輯由各個(gè)worker線程處理,worker的線程數(shù)由參數(shù)slave_parallel_workers決定。如果是32核的服務(wù)器,這個(gè)值可以設(shè)置為8~16.

雖然文章中很多人說(shuō)為了保證備庫(kù)的讀服務(wù),線程數(shù)為核數(shù)1/4~1/2,實(shí)際上我是不認(rèn)同的,應(yīng)該是主要看核數(shù)和讀寫(xiě)壓力,如果即使是64核的機(jī)器,并且寫(xiě)壓力不大,還是可以繼續(xù)保持當(dāng)前的配置;如果是讀寫(xiě)比例在10:1,那么這個(gè)線程數(shù)可以超過(guò)1/2。

為了保證事務(wù)的冪等性和原子性,我們需要做如下的要求:

1.冪等性:不能造成更新覆蓋。冪等性要求同一行的兩個(gè)事務(wù)必須分發(fā)到同一個(gè)worker。這里主要是為了防止由于客戶端的重試導(dǎo)致的事務(wù)重復(fù)或者是兩個(gè)事務(wù)之間的上下文依賴(lài)導(dǎo)致的數(shù)據(jù)不一致。

2.原子性:用一個(gè)事務(wù)必須由一個(gè)worker負(fù)責(zé)。相同事務(wù)的語(yǔ)句必須使用一個(gè)worker處理,否則可能導(dǎo)致一個(gè)worker失敗,另一個(gè)worker成功引入的數(shù)據(jù)不一致問(wèn)題。

1 并行復(fù)制策略介紹

注意,這部分是作者丁奇自己寫(xiě)的并行復(fù)制策略,非官方實(shí)現(xiàn)策略。

1.1 按表分發(fā)策略

按表分發(fā)事務(wù)的基本思想是:如果兩個(gè)事務(wù)更新不同的表,他們就可以并行。因?yàn)閿?shù)據(jù)是存儲(chǔ)在表里,所以按表分發(fā),可以保證兩個(gè)worker不會(huì)更新同一行。

如果有跨表的事務(wù),那么就需要把兩張表放在一起考慮。

圖片圖片

每個(gè)worker對(duì)應(yīng)一個(gè)hash表,用于保存當(dāng)前正在這個(gè)worker的“執(zhí)行隊(duì)列”里的事務(wù)所涉及的表。hash表的key是“庫(kù)名.表名”,value是一個(gè)數(shù)字,表示隊(duì)列中有多少事務(wù)修改這個(gè)表。

在有事務(wù)分配給 worker 時(shí),事務(wù)里面涉及的表會(huì)被加到對(duì)應(yīng)的 hash 表中。worker 執(zhí)行完成后,這個(gè)表會(huì)被從 hash 表中去掉。

圖 3 中,hash_table_1 表示,現(xiàn)在 worker_1 的“待執(zhí)行事務(wù)隊(duì)列”里,有 4 個(gè)事務(wù)涉及到 db1.t1 表,有 1 個(gè)事務(wù)涉及到 db1.t2 表;hash_table_2 表示,現(xiàn)在 worker_2 中有一個(gè)事務(wù)會(huì)更新到表 t3 的數(shù)據(jù)。

假設(shè)在圖中的情況下,coordinator 從中轉(zhuǎn)日志中讀入一個(gè)新事務(wù) T,這個(gè)事務(wù)修改的行涉及到表 t1 和 t3。

現(xiàn)在我們用事務(wù) T 的分配流程,來(lái)看一下分配規(guī)則:

  1. 由于事務(wù) T 中涉及修改表 t1,而 worker_1 隊(duì)列中有事務(wù)在修改表 t1,事務(wù) T 和隊(duì)列中的某個(gè)事務(wù)要修改同一個(gè)表的數(shù)據(jù),這種情況我們說(shuō)事務(wù) T 和 worker_1 是沖突的。
  2. 按照這個(gè)邏輯,順序判斷事務(wù) T 和每個(gè) worker 隊(duì)列的沖突關(guān)系,會(huì)發(fā)現(xiàn)事務(wù) T 跟 worker_2 也沖突。
  3. 事務(wù) T 跟多于一個(gè) worker 沖突,coordinator 線程就進(jìn)入等待。
  4. 每個(gè) worker 繼續(xù)執(zhí)行,同時(shí)修改 hash_table。假設(shè) hash_table_2 里面涉及到修改表 t3 的事務(wù)先執(zhí)行完成,就會(huì)從 hash_table_2 中把 db1.t3 這一項(xiàng)去掉。
  5. 這樣 coordinator 會(huì)發(fā)現(xiàn)跟事務(wù) T 沖突的 worker 只有 worker_1 了,因此就把它分配給 worker_1。
  6. coordinator 繼續(xù)讀下一個(gè)中轉(zhuǎn)日志,繼續(xù)分配事務(wù)。

也就是說(shuō),每個(gè)事務(wù)在分發(fā)的時(shí)候,跟所有 worker 的沖突關(guān)系包括以下三種情況:

  1. 如果跟所有 worker 都不沖突,coordinator 線程就會(huì)把這個(gè)事務(wù)分配給最空閑的 woker;
  2. 如果跟多于一個(gè) worker 沖突,coordinator 線程就進(jìn)入等待狀態(tài),直到和這個(gè)事務(wù)存在沖突關(guān)系的 worker 只剩下 1 個(gè);
  3. 如果只跟一個(gè) worker 沖突,coordinator 線程就會(huì)把這個(gè)事務(wù)分配給這個(gè)存在沖突關(guān)系的 worker。

這個(gè)按表分發(fā)的方案,在多個(gè)表負(fù)載均勻的場(chǎng)景里應(yīng)用效果很好。但是,如果碰到熱點(diǎn)表,比如所有的更新事務(wù)都會(huì)涉及到某一個(gè)表的時(shí)候,所有事務(wù)都會(huì)被分配到同一個(gè) worker 中,就變成單線程復(fù)制了。

1.2 按行分發(fā)策略

要解決熱點(diǎn)表的并行復(fù)制問(wèn)題,需要使用按行并行復(fù)制的方法。按行并行復(fù)制的核心思路就是:如果兩個(gè)事務(wù)沒(méi)有更新相同的行,在備庫(kù)上可以并行執(zhí)行,這時(shí)候就要求binlog的格式必須是row。這時(shí)候,我們判定事務(wù)T和worker沖突的規(guī)則是“修改同一行”。

按行復(fù)制和按表復(fù)制也是為每個(gè)worker分配一個(gè)hash表,只是按行復(fù)制時(shí),在考慮主鍵的同時(shí)還要考慮唯一索引的沖突。

CREATE TABLE `t1` (
  `id` int(11) NOT NULL,
  `a` int(11) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `a` (`a`)
) ENGINE=InnoDB;


insert into t1 values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5);

圖片這兩個(gè)事務(wù)的主鍵不一致,但是如果分到不同worker,有可能出現(xiàn)sessionB先行,這時(shí)候id=1對(duì)應(yīng)的a值還是1,就會(huì)出現(xiàn)唯一鍵沖突的問(wèn)題。因此,基于行的策略,需要考慮唯一鍵,即key為:“庫(kù)名+表名+索引a的名字+a的值”;

因此,上表例子中,表t1執(zhí)行sessionB語(yǔ)句,在binlog記錄了數(shù)據(jù)行修改前后各個(gè)字段的值,coordinator解析語(yǔ)句時(shí),這個(gè)事務(wù)的hash表有三個(gè)項(xiàng):

  • key=hash_func(db1+t1+"PRIMARY"+2),value=2;這里的value=2是因?yàn)樾薷那昂蟮膇d值不變,出現(xiàn)了兩次;
  • key=hash_func(db1+t1+"a"+2),value=1;表示會(huì)影響到表a=2的數(shù)據(jù)行;
  • key=hash_func(db1+t1+"a"+1),value=1;表示會(huì)影響到表a=1的數(shù)據(jù)行;

相比于按表并行分發(fā)策略,按行并行策略在決定線程分發(fā)的時(shí)候:

  • 需要消耗更多的計(jì)算資源;
  • 要能夠從 binlog 里面解析出表名、主鍵值和唯一索引的值。也就是說(shuō),主庫(kù)的 binlog 格式必須是 row;
  • 表必須有主鍵;
  • 不能有外鍵。表上如果有外鍵,級(jí)聯(lián)更新的行不會(huì)記錄在 binlog 中,這樣沖突檢測(cè)就不準(zhǔn)確。

對(duì)比按表分發(fā)和按行分發(fā)這兩個(gè)方案的話,按行分發(fā)策略的并行度更高。不過(guò),如果是要操作很多行的大事務(wù)的話,按行分發(fā)的策略有兩個(gè)問(wèn)題:

  • 耗費(fèi)內(nèi)存。比如一個(gè)語(yǔ)句要?jiǎng)h除 100 萬(wàn)行數(shù)據(jù),這時(shí)候 hash 表就要記錄 100 萬(wàn)個(gè)項(xiàng)。
  • 耗費(fèi) CPU。解析 binlog,然后計(jì)算 hash 值,對(duì)于大事務(wù),這個(gè)成本還是很高的。

所以,我在實(shí)現(xiàn)這個(gè)策略的時(shí)候會(huì)設(shè)置一個(gè)閾值,單個(gè)事務(wù)如果超過(guò)設(shè)置的行數(shù)閾值(比如,如果單個(gè)事務(wù)更新的行數(shù)超過(guò) 10 萬(wàn)行),就暫時(shí)退化為單線程模式,退化過(guò)程的邏輯大概是這樣的:

  • coordinator 暫時(shí)先 hold 住這個(gè)事務(wù);
  • 等待所有 worker 都執(zhí)行完成,變成空隊(duì)列;
  • coordinator 直接執(zhí)行這個(gè)事務(wù);
  • 恢復(fù)并行模式。

2 各數(shù)據(jù)庫(kù)版本并行復(fù)制策略

2.1 MySQL5.6并行復(fù)制策略

5.6版本開(kāi)始支持按庫(kù)并行復(fù)制的策略,由于是按庫(kù),自然粒度比較粗。這個(gè)策略的并行效果,取決于壓力模型,如果主庫(kù)上有多個(gè)DB,并且各個(gè)DB的壓力均衡,這個(gè)策略還好:

  • 構(gòu)建hash值只需要庫(kù)名,而且一個(gè)實(shí)例上的DB數(shù)不可能會(huì)很多,不會(huì)出現(xiàn)構(gòu)建100萬(wàn)個(gè)項(xiàng)這種情況;
  • 不要求binlog格式,因?yàn)閟tatement格式的binlog也可以很容易拿到庫(kù)名。

但是問(wèn)題也比較明顯,比如大促項(xiàng)目的數(shù)據(jù)庫(kù)和運(yùn)營(yíng)后臺(tái)的數(shù)據(jù)庫(kù)一定不是均衡的,因此,策略的應(yīng)用性有些差。

2.2 MariaDB并行復(fù)制策略

MariaDB是基于redo log的組提交(group commit)特性實(shí)現(xiàn):

  • 能夠在一個(gè)組內(nèi)提交的事務(wù),一定不會(huì)修改同一行;原因在于說(shuō):事務(wù)在執(zhí)行數(shù)據(jù)更新或者DDL時(shí)一定會(huì)加鎖,只有事務(wù)提交后才會(huì)釋放鎖,所以,借助于鎖的互斥性,保證了事務(wù)的原子性;
  • 主庫(kù)上可以并行執(zhí)行的事務(wù),備庫(kù)上也一定是可以并行執(zhí)行的;

在實(shí)現(xiàn)上:

  • 在一組里面一起提交的事務(wù),有一個(gè)相同的commit_id,下一組就是commit_id+1;
  • commit_id直接寫(xiě)入binlog中;
  • 傳到備庫(kù)應(yīng)用時(shí),相同commit_id事務(wù)分發(fā)到多個(gè)worker執(zhí)行;
  • 這一組全部執(zhí)行完成后,coordinator再去取下一批;

MariaDB的目標(biāo)就是“模擬主庫(kù)的并行執(zhí)行”,但是在具體實(shí)現(xiàn)上有些差距,畢竟主庫(kù)在一組事務(wù)commit時(shí),下一組事務(wù)同時(shí)處于“執(zhí)行中”狀態(tài)。如圖所示:

圖片圖片

MariaDB的執(zhí)行過(guò)程為:

圖片圖片

在備庫(kù)上執(zhí)行的時(shí)候,要等第一組事務(wù)完全執(zhí)行完成后,第二組事務(wù)才能開(kāi)始執(zhí)行,這樣系統(tǒng)的吞吐量就不夠。

另外,這個(gè)方案很容易被大事務(wù)拖后腿。假設(shè) trx2 是一個(gè)超大事務(wù),那么在備庫(kù)應(yīng)用的時(shí)候,trx1 和 trx3 執(zhí)行完成后,就只能等 trx2 完全執(zhí)行完成,下一組才能開(kāi)始執(zhí)行。這段時(shí)間,只有一個(gè) worker 線程在工作,是對(duì)資源的浪費(fèi)。

2.3 MySQL5.7版本并行復(fù)制策略

5.7版本提供了類(lèi)似于MariaDB策略,并增加參數(shù)slave-parallel-type控制并行策略:

  • 配置為 DATABASE,表示使用 MySQL 5.6 版本的按庫(kù)并行策略;
  • 配置為 LOGICAL_CLOCK,表示的就是類(lèi)似 MariaDB 的策略。不過(guò),MySQL 5.7 這個(gè)策略,針對(duì)并行度做了優(yōu)化。

優(yōu)化點(diǎn)在于,把階段進(jìn)行了提前,執(zhí)行中的事務(wù)可能會(huì)存在沖突,commit狀態(tài)的事務(wù)可能又有些延遲,MySQL5.7允許同時(shí)處于prepare狀態(tài)的事務(wù)執(zhí)行并行操作,因?yàn)橐呀?jīng)prepare狀態(tài)的事務(wù)一定也已經(jīng)通過(guò)鎖沖突的檢測(cè):

  • 同時(shí)處于prepare狀態(tài)的事務(wù)在備庫(kù)執(zhí)行時(shí)可以并行;
  • 處于prepare狀態(tài)的事務(wù)與commit狀態(tài)的事務(wù)之間,可以并行;

binlog 的組提交的時(shí)候,介紹過(guò)兩個(gè)參數(shù):

  • binlog_group_commit_sync_delay 參數(shù),表示延遲多少微秒后才調(diào)用 fsync;
  • binlog_group_commit_sync_no_delay_count 參數(shù),表示累積多少次以后才調(diào)用 fsync。

這兩個(gè)參數(shù)是用于故意拉長(zhǎng) binlog 從 write 到 fsync 的時(shí)間,以此減少 binlog 的寫(xiě)盤(pán)次數(shù)。在 MySQL 5.7 的并行復(fù)制策略里,它們可以用來(lái)制造更多的“同時(shí)處于 prepare 階段的事務(wù)”。這樣就增加了備庫(kù)復(fù)制的并行度。

也就是說(shuō),這兩個(gè)參數(shù),既可以“故意”讓主庫(kù)提交得慢些,又可以讓備庫(kù)執(zhí)行得快些。在 MySQL 5.7 處理備庫(kù)延遲的時(shí)候,可以考慮調(diào)整這兩個(gè)參數(shù)值,來(lái)達(dá)到提升備庫(kù)復(fù)制并發(fā)度的目的。

2.4 MySQL5.7.22版本的并行復(fù)制策略

MySQL 5.7.22 版本里,MySQL 增加了一個(gè)新的并行復(fù)制策略,基于 WRITESET 的并行復(fù)制,新增了一個(gè)參數(shù) binlog-transaction-dependency-tracking,用來(lái)控制是否啟用這個(gè)新策略。這個(gè)參數(shù)的可選值有以下三種。

  • COMMIT_ORDER,根據(jù)同時(shí)進(jìn)入 prepare 和 commit 來(lái)判斷是否可以并行的策略。
  • WRITESET,表示的是對(duì)于事務(wù)涉及更新的每一行,計(jì)算出這一行的 hash 值,組成集合 writeset。如果兩個(gè)事務(wù)沒(méi)有操作相同的行,也就是說(shuō)它們的 writeset 沒(méi)有交集,就可以并行。
  • WRITESET_SESSION,是在 WRITESET 的基礎(chǔ)上多了一個(gè)約束,即在主庫(kù)上同一個(gè)線程先后執(zhí)行的兩個(gè)事務(wù),在備庫(kù)執(zhí)行的時(shí)候,要保證相同的先后順序。

當(dāng)然為了唯一標(biāo)識(shí),這個(gè) hash 值是通過(guò)“庫(kù)名 + 表名 + 索引名 + 值”計(jì)算出來(lái)的。如果一個(gè)表上除了有主鍵索引外,還有其他唯一索引,那么對(duì)于每個(gè)唯一索引,insert 語(yǔ)句對(duì)應(yīng)的 writeset 就要多增加一個(gè) hash 值。

這跟前面介紹的基于 MySQL 5.5 版本的按行分發(fā)的策略是差不多的。不過(guò),MySQL 官方的這個(gè)實(shí)現(xiàn)還是有很大的優(yōu)勢(shì):

  • writeset 是在主庫(kù)生成后直接寫(xiě)入到 binlog 里面的,這樣在備庫(kù)執(zhí)行的時(shí)候,不需要解析 binlog 內(nèi)容(event 里的行數(shù)據(jù)),節(jié)省了很多計(jì)算量;
  • 不需要把整個(gè)事務(wù)的 binlog 都掃一遍才能決定分發(fā)到哪個(gè) worker,更省內(nèi)存;
  • 由于備庫(kù)的分發(fā)策略不依賴(lài)于 binlog 內(nèi)容,所以 binlog 是 statement 格式也是可以的。

因此,MySQL 5.7.22 的并行復(fù)制策略在通用性上還是有保證的。當(dāng)然,對(duì)于“表上沒(méi)主鍵”和“外鍵約束”的場(chǎng)景,WRITESET 策略也是沒(méi)法并行的,也會(huì)暫時(shí)退化為單線程模型。

責(zé)任編輯:武曉燕 來(lái)源: 陸隊(duì)長(zhǎng)
相關(guān)推薦

2013-11-13 13:44:48

淘寶雙十一背后

2022-03-09 12:26:04

MySQL高可用性主備延遲

2012-11-13 10:27:49

雙十一技術(shù)討論

2015-11-10 18:37:59

Taste?Analy

2014-12-01 10:01:19

2018-11-12 10:12:45

星圖數(shù)據(jù)

2024-05-31 13:55:25

2014-11-11 14:51:56

2013-08-22 09:36:45

阿里巴巴王堅(jiān)阿里云

2016-11-15 07:56:13

雙十一云計(jì)算科技新聞早報(bào)

2019-12-05 16:13:25

雙十一互聯(lián)網(wǎng)消費(fèi)電商

2015-11-10 20:54:31

網(wǎng)購(gòu)安全雙十一

2015-10-22 11:47:28

E店寶ERP雙十一

2012-12-26 10:17:55

大數(shù)據(jù)雙十一天貓

2024-08-20 16:13:52

2013-11-11 13:30:42

閃存

2016-11-10 14:28:16

雙十一阿里網(wǎng)購(gòu)

2023-11-23 13:17:39

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

2022-02-27 14:37:53

MySQL主備數(shù)據(jù)

2012-11-10 21:21:59

淘寶大數(shù)據(jù)雙十一
點(diǎn)贊
收藏

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