日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

前言

在之前我們已經(jīng)講解了一主一從,雙主雙從的MySQL集群搭建,在單機(jī)應(yīng)用的時(shí)候看起來(lái)沒(méi)有問(wèn)題,但是在企業(yè)的生產(chǎn)環(huán)境中,在很多情況下都會(huì)有復(fù)制延遲的問(wèn)題。所以我來(lái)了?。。?/p>

? 主從復(fù)制的原理我們?cè)诖颂幘筒辉儋樖隽耍耙呀?jīng)講過(guò)了,這是一個(gè)老生常談的問(wèn)題,原理性質(zhì)的也幾乎在面試中問(wèn)爛了,這些原理性質(zhì)的東西并不是很難,但是你需要注意了,主從復(fù)制的延遲問(wèn)題會(huì)成為一個(gè)難點(diǎn),能非常全面的考驗(yàn)同學(xué)們的技術(shù)實(shí)力。

1、如何查看同步延遲狀態(tài)?

? 在從服務(wù)器上通過(guò) show slave status 查看具體的參數(shù),有幾個(gè)參數(shù)比較重要:

master_log_file: slave中的IO線程正在讀取的主服務(wù)器二進(jìn)制日志文件的名稱

read_master_log_pos: 在當(dāng)前的主服務(wù)器二進(jìn)制日志中,slave中的IO線程已經(jīng)讀取的位置

relay_log_file: sql線程當(dāng)前正在讀取和執(zhí)行的中繼日志文件的名稱

relay_log_pos: 在當(dāng)前的中繼日志中,sql線程已經(jīng)讀取和執(zhí)行的位置

relay_master_log_file: 由sql線程執(zhí)行的包含多數(shù)近期事件的主服務(wù)器二進(jìn)制日志文件的名稱

slave_io_running: IO線程是否被啟動(dòng)并成功地連接到主服務(wù)器上

slave_sql_running: sql線程是否被啟動(dòng)

seconds_behind_master: 從屬服務(wù)器sql線程和從屬服務(wù)器IO線程之間的事件差距,單位以秒計(jì)

? 在觀察同步延遲的時(shí)候,上述的幾個(gè)參數(shù)都是比較重要的,其中有一個(gè)最最重要的參數(shù)需要同學(xué)們引起注意,那就是seconds_behind_master,這個(gè)參數(shù)就表示當(dāng)前備庫(kù)延遲了多長(zhǎng)時(shí)間,那么這個(gè)值是如何計(jì)算的呢?

? 在進(jìn)行主從復(fù)制的時(shí)候,需要注意以下幾個(gè)關(guān)鍵的時(shí)刻:

? 1、主庫(kù)A執(zhí)行完成一個(gè)事務(wù),寫入binlog,我們把這個(gè)時(shí)刻記為T1;

? 2、之后傳給備庫(kù)B,我們把備庫(kù)B接受完這個(gè)binlog的時(shí)刻記為T2;

? 3、備庫(kù)B執(zhí)行完成這個(gè)事務(wù),我們把這個(gè)時(shí)刻記為T3;

? 所謂的主備延遲就是同一個(gè)事務(wù),在備庫(kù)執(zhí)行完成的時(shí)間和主庫(kù)執(zhí)行完成的時(shí)間之間的差值,也就是T3-T1。SBM在進(jìn)行計(jì)算的時(shí)候也是按照這樣的方式,每個(gè)事務(wù)的binlog中都有一個(gè)時(shí)間字段,用于記錄主庫(kù)寫入的時(shí)間,備庫(kù)取出當(dāng)前正在執(zhí)行的事務(wù)的時(shí)間字段的值,計(jì)算它與當(dāng)前系統(tǒng)時(shí)間的差值,得到SBM。

? 如果剛剛的流程聽明白了,那么下面我們就要開始分析產(chǎn)生這個(gè)時(shí)間差值的原因有哪些了,以方便我們更好的解決生產(chǎn)環(huán)境中存在的問(wèn)題。

2、主從復(fù)制延遲產(chǎn)生的原因有哪些?

? 1、在某些部署環(huán)境中,備庫(kù)所在的機(jī)器性能要比主庫(kù)所在的機(jī)器性能差。此時(shí)如果機(jī)器的資源不足的話就會(huì)影響備庫(kù)同步的效率;

? 2、備庫(kù)充當(dāng)了讀庫(kù),一般情況下主要寫的壓力在于主庫(kù),那么備庫(kù)會(huì)提供一部分讀的壓力,而如果備庫(kù)的查詢壓力過(guò)大的話,備庫(kù)的查詢消耗了大量的CPU資源,那么必不可少的就會(huì)影響同步的速度

? 3、大事務(wù)執(zhí)行,如果主庫(kù)的一個(gè)事務(wù)執(zhí)行了10分鐘,而binlog的寫入必須要等待事務(wù)完成之后,才會(huì)傳入備庫(kù),那么此時(shí)在開始執(zhí)行的時(shí)候就已經(jīng)延遲了10分鐘了

? 4、主庫(kù)的寫操作是順序?qū)慴inlog,從庫(kù)單線程去主庫(kù)順序讀binlog,從庫(kù)取到binlog之后在本地執(zhí)行。mysql的主從復(fù)制都是單線程的操作,但是由于主庫(kù)是順序?qū)?,所以效率很高,而從?kù)也是順序讀取主庫(kù)的日志,此時(shí)的效率也是比較高的,但是當(dāng)數(shù)據(jù)拉取回來(lái)之后變成了隨機(jī)的操作,而不是順序的,所以此時(shí)成本會(huì)提高。

? 5、 從庫(kù)在同步數(shù)據(jù)的同時(shí),可能跟其他查詢的線程發(fā)生鎖搶占的情況,此時(shí)也會(huì)發(fā)生延時(shí)。

? 6、 當(dāng)主庫(kù)的TPS并發(fā)非常高的時(shí)候,產(chǎn)生的DDL數(shù)量超過(guò)了一個(gè)線程所能承受的范圍的時(shí)候,那么也可能帶來(lái)延遲

? 7、 在進(jìn)行binlog日志傳輸?shù)臅r(shí)候,如果網(wǎng)絡(luò)帶寬也不是很好,那么網(wǎng)絡(luò)延遲也可能造成數(shù)據(jù)同步延遲

? 這些就是可能會(huì)造成備庫(kù)延遲的原因

3、如何解決復(fù)制延遲的問(wèn)題

? 先說(shuō)一些虛的東西,什么叫虛的東西呢?就是一聽上去感覺(jué)很有道理,但是在實(shí)施或者實(shí)際的業(yè)務(wù)場(chǎng)景中可能難度很大或者很難實(shí)現(xiàn),下面我們從幾個(gè)方面來(lái)進(jìn)行描述:

1、架構(gòu)方面

? 1、業(yè)務(wù)的持久化層的實(shí)現(xiàn)采用分庫(kù)架構(gòu),讓不同的業(yè)務(wù)請(qǐng)求分散到不同的數(shù)據(jù)庫(kù)服務(wù)上,分散單臺(tái)機(jī)器的壓力

? 2、服務(wù)的基礎(chǔ)架構(gòu)在業(yè)務(wù)和mysql之間加入緩存層,減少mysql的讀的壓力,但是需要注意的是,如果數(shù)據(jù)經(jīng)常要發(fā)生修改,那么這種設(shè)計(jì)是不合理的,因?yàn)樾枰l繁地去更新緩存中的數(shù)據(jù),保持?jǐn)?shù)據(jù)的一致性,導(dǎo)致緩存的命中率很低,所以此時(shí)就要慎用緩存了

? 3、使用更好的硬件設(shè)備,比如cpu,ssd等,但是這種方案一般對(duì)于公司而言不太能接受,原因也很簡(jiǎn)單,會(huì)增加公司的成本,而一般公司其實(shí)都很摳門,所以意義也不大,但是你要知道這也是解決問(wèn)題的一個(gè)方法,只不過(guò)你需要評(píng)估的是投入產(chǎn)出比而已。

2、從庫(kù)配置方面

1、修改sync_binlog的參數(shù)的值

? 想要合理設(shè)置此參數(shù)的值必須要清楚地知道binlog的寫盤的流程:

?

一篇文帶你解決mysql的主從復(fù)制延遲問(wèn)題

 

? 可以看到,每個(gè)線程有自己的binlog cache,但是共用同一份binlog。

? 圖中的write,指的就是把日志寫入到文件系統(tǒng)的page cache,并沒(méi)有把數(shù)據(jù)持久化到磁盤,所以速度快

? 圖中的fsync,才是將數(shù)據(jù)持久化到磁盤的操作。一般情況下,我們認(rèn)為fsync才占用磁盤的IOPS

? 而write和fsync的時(shí)機(jī)就是由參數(shù)sync_binlog來(lái)進(jìn)行控制的。

? 1、當(dāng)sync_binlog=0的時(shí)候,表示每次提交事務(wù)都只write,不fsync

? 2、當(dāng)sync_binlog=1的時(shí)候,表示每次提交事務(wù)都執(zhí)行fsync

? 3、當(dāng)sync_binlog=N的時(shí)候,表示每次提交事務(wù)都write,但積累N個(gè)事務(wù)后才fsync。

? 一般在公司的大部分應(yīng)用場(chǎng)景中,我們建議將此參數(shù)的值設(shè)置為1,因?yàn)檫@樣的話能夠保證數(shù)據(jù)的安全性,但是如果出現(xiàn)主從復(fù)制的延遲問(wèn)題,可以考慮將此值設(shè)置為100~1000中的某個(gè)數(shù)值,非常不建議設(shè)置為0,因?yàn)樵O(shè)置為0的時(shí)候沒(méi)有辦法控制丟失日志的數(shù)據(jù)量,但是如果是對(duì)安全性要求比較高的業(yè)務(wù)系統(tǒng),這個(gè)參數(shù)產(chǎn)生的意義就不是那么大了。

? 2、直接禁用salve上的binlog,當(dāng)從庫(kù)的數(shù)據(jù)在做同步的時(shí)候,有可能從庫(kù)的binlog也會(huì)進(jìn)行記錄,此時(shí)的話肯定也會(huì)消耗io的資源,因此可以考慮將其關(guān)閉,但是需要注意,如果你搭建的集群是級(jí)聯(lián)的模式的話,那么此時(shí)的binlog也會(huì)發(fā)送到另外一臺(tái)從庫(kù)里方便進(jìn)行數(shù)據(jù)同步,此時(shí)的話,這個(gè)配置項(xiàng)也不會(huì)起到太大的作用。

? 3、設(shè)置
innodb_flush_log_at_trx_commit 屬性,這個(gè)屬性在我講日志的時(shí)候講過(guò),用來(lái)表示每一次的事務(wù)提交是否需要把日志都寫入磁盤,這是很浪費(fèi)時(shí)間的,一共有三個(gè)屬性值,分別是0(每次寫到服務(wù)緩存,一秒鐘刷寫一次),1(每次事務(wù)提交都刷寫一次磁盤),2(每次寫到os緩存,一秒鐘刷寫一次),一般情況下我們推薦設(shè)置成2,這樣就算mysql的服務(wù)宕機(jī)了,卸載os緩存中的數(shù)據(jù)也會(huì)進(jìn)行持久化。

4、從根本上解決主從復(fù)制的延遲問(wèn)題

? 很多同學(xué)在自己線上的業(yè)務(wù)系統(tǒng)中都使用了mysql的主從復(fù)制,但是大家需要注意的是,并不是所有的場(chǎng)景都適合主從復(fù)制,一般情況下是讀要遠(yuǎn)遠(yuǎn)多于寫的應(yīng)用,同時(shí)讀的時(shí)效性要求不那么高的場(chǎng)景。如果真實(shí)場(chǎng)景中真的要求立馬讀取到更新之后的數(shù)據(jù),那么就只能強(qiáng)制讀取主庫(kù)的數(shù)據(jù),所以在進(jìn)行實(shí)現(xiàn)的時(shí)候要考慮實(shí)際的應(yīng)用場(chǎng)景,不要為了技術(shù)而技術(shù),這是很嚴(yán)重的事情。

? 在mysql5.6版本之后引入了一個(gè)概念,就是我們通常說(shuō)的并行復(fù)制,如下圖:

一篇文帶你解決mysql的主從復(fù)制延遲問(wèn)題

 

? 通過(guò)上圖我們可以發(fā)現(xiàn)其實(shí)所謂的并行復(fù)制,就是在中間添加了一個(gè)分發(fā)的環(huán)節(jié),也就是說(shuō)原來(lái)的sql_thread變成了現(xiàn)在的coordinator組件,當(dāng)日志來(lái)了之后,coordinator負(fù)責(zé)讀取日志信息以及分發(fā)事務(wù),真正的日志執(zhí)行的過(guò)程是放在了worker線程上,由多個(gè)線程并行的去執(zhí)行。

-- 查看并行的slave的線程的個(gè)數(shù),默認(rèn)是0.表示單線程
show global variables like 'slave_parallel_workers';
-- 根據(jù)實(shí)際情況保證開啟多少線程
set global slave_parallel_workers = 4;
-- 設(shè)置并發(fā)復(fù)制的方式,默認(rèn)是一個(gè)線程處理一個(gè)庫(kù),值為database
show global variables like '%slave_parallel_type%';
-- 停止slave
stop slave;
-- 設(shè)置屬性值
set global slave_parallel_type='logical_check';
-- 開啟slave
start slave
-- 查看線程數(shù)
show full processlist;

? 通過(guò)上述的配置可以完成我們說(shuō)的并行復(fù)制,但是此時(shí)你需要思考幾個(gè)問(wèn)題

? 1、在并行操作的時(shí)候,可能會(huì)有并發(fā)的事務(wù)問(wèn)題,我們的備庫(kù)在執(zhí)行的時(shí)候可以按照輪訓(xùn)的方式發(fā)送給各個(gè)worker嗎?

? 答案是不行的,因?yàn)槭聞?wù)被分發(fā)給worker以后,不同的worker就開始獨(dú)立執(zhí)行了,但是,由于CPU的不同調(diào)度策略,很可能第二個(gè)事務(wù)最終比第一個(gè)事務(wù)先執(zhí)行,而如果剛剛好他們修改的是同一行數(shù)據(jù),那么因?yàn)閳?zhí)行順序的問(wèn)題,可能導(dǎo)致主備的數(shù)據(jù)不一致。

? 2、同一個(gè)事務(wù)的多個(gè)更新語(yǔ)句,能不能分給不同的worker來(lái)執(zhí)行呢?

? 答案是也不行,舉個(gè)例子,一個(gè)事務(wù)更新了表t1和表t2中的各一行,如果這兩條更新語(yǔ)句被分到不同worker的話,雖然最終的結(jié)果是主備一致的,但如果表t1執(zhí)行完成的瞬間,備庫(kù)上有一個(gè)查詢,就會(huì)看到這個(gè)事務(wù)更新了一半的結(jié)果,破壞了事務(wù)邏輯的隔離性。

? 我們通過(guò)講解上述兩個(gè)問(wèn)題的最主要目的是為了說(shuō)明一件事,就是coordinator在進(jìn)行分發(fā)的時(shí)候,需要遵循的策略是什么?

? 1、不能造成更新覆蓋。這就要求更新同一行的兩個(gè)事務(wù),必須被分發(fā)到同一個(gè)worker中。

? 2、同一個(gè)事務(wù)不能被拆開,必須放到同一個(gè)worker中。

? 聽完上面的描述,我們來(lái)說(shuō)一下具體實(shí)現(xiàn)的原理和過(guò)程。

? 如果讓我們自己來(lái)設(shè)計(jì)的話,我們應(yīng)該如何操作呢?這是一個(gè)值得思考的問(wèn)題。其實(shí)如果按照實(shí)際的操作的話,我們可以按照粒度進(jìn)行分類,分為按庫(kù)分發(fā),按表分發(fā),按行分發(fā)。

? 其實(shí)不管按照什么方式進(jìn)行分發(fā),大家需要注意的就是在分發(fā)的時(shí)候必須要滿足我們上面說(shuō)的兩條規(guī)則,所以當(dāng)我們進(jìn)行分發(fā)的時(shí)候要在每一個(gè)worker上定義一個(gè)hash表,用來(lái)保存當(dāng)前這個(gè)work正在執(zhí)行的事務(wù)所涉及到的表。hash表的key值按照不同的粒度需要存儲(chǔ)不同的值:

? 按庫(kù)分發(fā):key值是數(shù)據(jù)庫(kù)的名字,這個(gè)比較簡(jiǎn)單

? 按表分發(fā):key值是庫(kù)名+表名

? 按行分發(fā):key值是庫(kù)名+表名+唯一鍵

1、MySQL5.6版本的并行復(fù)制策略

? 其實(shí)從mysql的5.6版本開始就已經(jīng)支持了并行復(fù)制,只是支持的粒度是按庫(kù)并行,這也是為什么現(xiàn)在的版本中可以選擇類型為database,其實(shí)說(shuō)的就是支持按照庫(kù)進(jìn)行并行復(fù)制。

? 但是其實(shí)用過(guò)的同學(xué)應(yīng)該都知道,這個(gè)策略的并行效果,取決于壓力模型。如果在主庫(kù)上有多個(gè)DB,并且各個(gè)DB的壓力均衡,使用這個(gè)策略的效果會(huì)很好,但是如果主庫(kù)的所有表都放在同一DB上,那么所有的操作都會(huì)分發(fā)給一個(gè)worker,變成單線程操作了,那么這個(gè)策略的效果就不好了,因此在實(shí)際的生產(chǎn)環(huán)境中,用的并不是特別多。

2、mariaDB的并行復(fù)制策略

? 在mysql5.7的時(shí)候采用的是基于組提交的并行復(fù)制,換句話說(shuō),slave服務(wù)器的回放與主機(jī)是一致的,即主庫(kù)是如何并行執(zhí)行的那么slave就如何怎樣進(jìn)行并行回放,這點(diǎn)其實(shí)是參考了mariaDB的并行復(fù)制,下面我們來(lái)看下其實(shí)現(xiàn)原理。

? mariaDB的并行復(fù)制策略利用的就是這個(gè)特性:

? 1、能夠在同一組里提交的事務(wù),一定不會(huì)修改同一行;

? 2、主庫(kù)上可以并行執(zhí)行的事務(wù),備庫(kù)上也一定是可以并行執(zhí)行的。

? 在實(shí)現(xiàn)上,mariaDB是這么做的:

? 1、在一組里面一起提交的事務(wù),有一個(gè)相同的commit_id,下一組就是commit_id+1;

? 2、commit_id直接寫到binlog里面;

? 3、傳到備庫(kù)應(yīng)用的時(shí)候,相同commit_id的事務(wù)會(huì)分發(fā)到多個(gè)worker執(zhí)行;

? 4、這一組全部執(zhí)行完成后,coordinator再去取下一批。

? 這是mariaDB的并行復(fù)制策略,大體上看起來(lái)是沒(méi)有問(wèn)題的,但是你仔細(xì)觀察的話會(huì)發(fā)現(xiàn)他并沒(méi)有實(shí)現(xiàn)“真正的模擬主庫(kù)并發(fā)度”這個(gè)目標(biāo),在主庫(kù)上,一組事務(wù)在commit的時(shí)候,下一組事務(wù)是同時(shí)處于“執(zhí)行中”狀態(tài)的。

? 我們真正想要達(dá)到的并行復(fù)制應(yīng)該是如下的狀態(tài),也就是說(shuō)當(dāng)?shù)谝唤M事務(wù)提交的是,下一組事務(wù)是運(yùn)行的狀態(tài),當(dāng)?shù)谝唤M事務(wù)提交完成之后,下一組事務(wù)會(huì)立刻變成commit狀態(tài)。

一篇文帶你解決mysql的主從復(fù)制延遲問(wèn)題

 

? 但是按照mariaDB的并行復(fù)制策略,那么備庫(kù)上的執(zhí)行狀態(tài)會(huì)變成如下所示:

一篇文帶你解決mysql的主從復(fù)制延遲問(wèn)題

 

? 可以看到,這張圖跟上面這張圖的最大區(qū)別在于,備庫(kù)上執(zhí)行的時(shí)候必須要等第一組事務(wù)執(zhí)行完成之后,第二組事務(wù)才能開始執(zhí)行,這樣系統(tǒng)的吞吐量就不夠了。而且這個(gè)方案很容易被大事務(wù)拖后腿,如果trx2是一個(gè)大事務(wù),那么在備庫(kù)應(yīng)用的時(shí)候,trx1和trx3執(zhí)行完成之后,就只能等trx2完全執(zhí)行完成,下一組才能開始執(zhí)行,這段時(shí)間,只有一個(gè)worker線程在工作,是對(duì)資源的浪費(fèi)。

3、mysql5.7的并行復(fù)制策略

? mysql5.7版本的時(shí)候,根據(jù)mariaDB的并行復(fù)制策略,做了相應(yīng)的優(yōu)化調(diào)整后,提供了自己的并行復(fù)制策略,并且可以通過(guò)參數(shù)slave-parallel-type來(lái)控制并行復(fù)制的策略:

? 1、當(dāng)配置的值為DATABASE的時(shí)候,表示使用5.6版本的按庫(kù)并行策略;

? 2、當(dāng)配置的值為L(zhǎng)OGICAL_CLOCK的時(shí)候,表示跟mariaDB相同的策略。

? 此時(shí),大家需要思考一個(gè)問(wèn)題:同時(shí)處于執(zhí)行狀態(tài)的所有事務(wù),是否可以并行?

? 答案是不行的,因?yàn)槎鄠€(gè)執(zhí)行中的事務(wù)是有可能出現(xiàn)鎖沖突的,鎖沖突之后就會(huì)產(chǎn)生鎖等待問(wèn)題。

? 在mariaDB中,所有處于commit狀態(tài)的事務(wù)是可以并行,因?yàn)槿绻躢ommit的話就說(shuō)明已經(jīng)沒(méi)有鎖的問(wèn)題,但是大家回想下,我們mysql的日志提交是兩階段提交,如下圖,其實(shí)只要處于prepare狀態(tài)就已經(jīng)表示沒(méi)有鎖的問(wèn)題了。

一篇文帶你解決mysql的主從復(fù)制延遲問(wèn)題

 

? 因此,mysql5.7的并行復(fù)制策略的思想是:

? 1、同時(shí)處于prepare狀態(tài)的事務(wù),在備庫(kù)執(zhí)行是可以并行的。

? 2、處于prepare狀態(tài)的事務(wù),與處于commit狀態(tài)的事務(wù)之間,在備庫(kù)上執(zhí)行也是可以并行的。

? 基于這樣的處理機(jī)制,我們可以將大部分的日志處于prepare狀態(tài),因此可以設(shè)置

? 1、
binlog_group_commit_sync_delay 參數(shù),表示延遲多少微秒后才調(diào)用 fsync;

? 2、
binlog_group_commit_sync_no_delay_count 參數(shù),表示累積多少次以后才調(diào)用 fsync。

5、基于GTID的主從復(fù)制問(wèn)題

? 在我們之前講解的主從復(fù)制實(shí)操中,每次想要復(fù)制,必須要在備機(jī)上執(zhí)行對(duì)應(yīng)的命令,如下所示:

change master to master_host='192.168.85.11',master_user='root',master_password='123456',master_port=3306,master_log_file='master-bin.000001',master_log_pos=154;

? 在此配置中我們必須要知道具體的binlog是哪個(gè)文件,同時(shí)在文件的哪個(gè)位置開始復(fù)制,正常情況下也沒(méi)有問(wèn)題,但是如果是一個(gè)主備主從集群,那么如果主機(jī)宕機(jī),當(dāng)從機(jī)開始工作的時(shí)候,那么備機(jī)就要同步從機(jī)的位置,此時(shí)位置可能跟主機(jī)的位置是不同的,因此在這種情況下,再去找位置就會(huì)比較麻煩,所以在5.6版本之后出來(lái)一個(gè)基于GTID的主從復(fù)制。

? GTID(global transaction id)是對(duì)于一個(gè)已提交事務(wù)的編號(hào),并且是一個(gè)全局唯一的編號(hào)。GTID實(shí)際上是由UUID+TID組成的,其中UUID是mysql實(shí)例的唯一標(biāo)識(shí),TID表示該實(shí)例上已經(jīng)提交的事務(wù)數(shù)量,并且隨著事務(wù)提交單調(diào)遞增。這種方式保證事務(wù)在集群中有唯一的ID,強(qiáng)化了主備一致及故障恢復(fù)能力。

1、基于GTID的搭建

? 1、修改mysql配置文件,添加如下配置

gtid_mode=on
enforce-gtid-consistency=true

? 2、重啟主從的服務(wù)

? 3、從庫(kù)執(zhí)行如下命令

change master to master_host='192.168.85.111',master_user='root',master_password='123456'
,master_auto_position=1;

? 4、主庫(kù)從庫(kù)插入數(shù)據(jù)測(cè)試。

2、基于GTID的并行復(fù)制

? 無(wú)論是什么方式的主從復(fù)制其實(shí)原理相差都不是很大,關(guān)鍵點(diǎn)在于將組提交的信息存放在GTId中。

show binlog events in 'lian-bin.000001';
一篇文帶你解決mysql的主從復(fù)制延遲問(wèn)題

 

previous_gtids:用于表示上一個(gè)binlog最后一個(gè)gtid的位置,每個(gè)binlog只有一個(gè)。

gtid:當(dāng)開啟gtid的時(shí)候,每一個(gè)操作語(yǔ)句執(zhí)行前會(huì)添加一個(gè)gtid事件,記錄當(dāng)前全局事務(wù)id,組提交信息被保存在gtid事件中,有兩個(gè)關(guān)鍵字段,last_committed,sequence_number用來(lái)標(biāo)識(shí)組提交信息。

一篇文帶你解決mysql的主從復(fù)制延遲問(wèn)題

 

上述日志看起來(lái)可能比較麻煩,可以使用如下命令執(zhí)行:

一篇文帶你解決mysql的主從復(fù)制延遲問(wèn)題

 

其中l(wèi)ast_committed表示事務(wù)提交的時(shí)候,上次事務(wù)提交的編號(hào),如果事務(wù)具有相同的last_committed值表示事務(wù)就在一個(gè)組內(nèi),在備庫(kù)執(zhí)行的時(shí)候可以并行執(zhí)行。同時(shí)大家還要注意,每個(gè)last_committed的值都是上一個(gè)組事務(wù)的sequence_number值。

看到此處,大家可能會(huì)有疑問(wèn),如果我們不開啟gtid,分組信息該如何保存呢?

其實(shí)是一樣的,當(dāng)沒(méi)有開啟的時(shí)候,數(shù)據(jù)庫(kù)會(huì)有一個(gè)Anonymous_Gtid,用來(lái)保存組相關(guān)的信息。

如果大家想看并行的效果的話,可以執(zhí)行如下代碼:

package com.mashibing;

import JAVA.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;

public class ConCurrentInsert  extends Thread{
    public void run() {
        String url = "jdbc:mysql://192.168.85.111/lian2";
        String name = "com.mysql.jdbc.Driver";
        String user = "root";
        String password = "123456";
        Connection conn = null;
        try {
            Class.forName(name);
            conn = DriverManager.getConnection(url, user, password);//獲取連接
            conn.setAutoCommit(false);//關(guān)閉自動(dòng)提交,不然conn.commit()運(yùn)行到這句會(huì)報(bào)錯(cuò)
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        // 開始時(shí)間
        Long begin = new Date().getTime();
        // sql前綴
        String prefix = "INSERT INTO t1 (id,age) VALUES ";
        try {
            // 保存sql后綴
            StringBuffer suffix = new StringBuffer();
            // 設(shè)置事務(wù)為非自動(dòng)提交
            conn.setAutoCommit(false);
            // 比起st,pst會(huì)更好些
            PreparedStatement pst = (PreparedStatement) conn.prepareStatement("");//準(zhǔn)備執(zhí)行語(yǔ)句
            // 外層循環(huán),總提交事務(wù)次數(shù)
            for (int i = 1; i <= 10; i++) {
                suffix = new StringBuffer();
                // 第j次提交步長(zhǎng)
                for (int j = 1; j <= 10; j++) {
                    // 構(gòu)建SQL后綴
                    suffix.Append("(" +i*j+","+i*j+"),");
                }
                // 構(gòu)建完整SQL
                String sql = prefix + suffix.substring(0, suffix.length() - 1);
                // 添加執(zhí)行SQL
                pst.addBatch(sql);
                // 執(zhí)行操作
                pst.executeBatch();
                // 提交事務(wù)
                conn.commit();
                // 清空上一次添加的數(shù)據(jù)
                suffix = new StringBuffer();
            }
            // 頭等連接
            pst.close();
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        // 結(jié)束時(shí)間
        Long end = new Date().getTime();
        // 耗時(shí)
        System.out.println("100萬(wàn)條數(shù)據(jù)插入花費(fèi)時(shí)間 : " + (end - begin) / 1000 + " s"+"  插入完成");
    }

    public static void main(String[] args) {
        for (int i = 1; i <=10; i++) {
            new ConCurrentInsert().start();
        }
    }
}

分享到:
標(biāo)簽:主從 復(fù)制
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定