mysql 5.7变化_从MySQL 5.5到5.7看复制的演进
概要:MySQL 5.5 支持單線程模式復(fù)制,MySQL 5.6 支持庫級(jí)別的并行復(fù)制,MySQL 5.7 支持事務(wù)級(jí)別并行復(fù)制。結(jié)合這個(gè)主線我們可以來分析一下MySQL以及社區(qū)發(fā)展的一個(gè)前因后果。
MySQL5.5,對(duì)于復(fù)制我們可以這樣理解:主庫有個(gè) dump binlog thread 不停的 dump binlog,然后以event為單位發(fā)送給從庫 的 iothread,iothread 收到主庫傳過來的event寫入relaylog ,隨后sql_thread 讀取relaylog 對(duì)這些event以事務(wù)為單位進(jìn)行回放。
那么對(duì)于MySQL 5.5這個(gè)版本,在我們的使用過程中遇到那些問題,或者有那些不便呢?
首先DB壓力偏大時(shí),從庫帶來的延遲較大,影響只讀業(yè)務(wù)
由于新硬件的發(fā)展,SSD的引入和多core的CPU,master節(jié)點(diǎn)的并發(fā)處理能力持續(xù)提升,slave節(jié)點(diǎn)完全按照binlog寫入順序的單線程回放,已完全跟不上master節(jié)點(diǎn)的吞吐能力。
在不考慮主從硬件配置差異情況下,延遲大的其根本原因在于:Master壓力過大,而Slave是單線程回放日志。那么要解決這個(gè)問題,從技術(shù)上來說可以把單線程變?yōu)槎嗑€程,利用并行帶來的優(yōu)勢(shì);從業(yè)務(wù)上來說可以進(jìn)行拆庫,把一些業(yè)務(wù)線或者功能模塊獨(dú)立出去;更進(jìn)一步我們可以拆表,把壓力分擔(dān)到多個(gè)Master上去。
假如我們?cè)诓蛔儎?dòng)業(yè)務(wù)的情況下,從技術(shù)面來解決這個(gè)問題有哪些方向呢:
社區(qū)的解決方案:阿里開源的canal,基于表級(jí)別并行同步,可以減小同步延遲時(shí)間
官方的解決方案:在2011年10月份發(fā)布了一個(gè)里程碑版本基于schema級(jí)別的并行復(fù)制[MySQL5.6.3 (multi-threaded slave)],以及基于group Commit的 MySQL5.7版本,最大化還原主庫并行度。
MySQL5.6,對(duì)于復(fù)制我們可以這樣理解,主庫有個(gè) dump binlog thread 不停的 dump binlog,然后以event為單位發(fā)送給從庫 的 iothread,iothread 收到主庫傳過來的event寫入relaylog。【隨后的事情和MySQL5.5就發(fā)生了一些變化】,由coordinator線程來讀取relaylog,然后根據(jù)不同的db以事務(wù)為單位分配到不同的work線程。如果binlog row event操作的是不同的schema的對(duì)象,在確定沒有DDL和foreign key依賴的情況下,就可以實(shí)現(xiàn)并行復(fù)制。
MySQL5.7可以說是最大還原了主庫上的并行,在基于Group Commit的基礎(chǔ)上,所有在主庫上能夠完成prepared的語句表示沒有數(shù)據(jù)沖突,分配成相同的lastcommitted,就可以在slave節(jié)點(diǎn)并行復(fù)制。 那么它是如何識(shí)別那些事務(wù)是一起提交的呢?其實(shí)就是在gtid event 中增加了兩個(gè)字段【int64 lastcommitted;int64 sequencenumber】,當(dāng)slave的coordinator線程在分發(fā)這些event的時(shí)候,具有相同lastcommitted 的事務(wù)(event的集合)就可以同時(shí)發(fā)送給不同的work線程,達(dá)到并行同步的目的。
小結(jié):就并行復(fù)制,按粒度區(qū)分有三種策略,粒度從粗到細(xì)是按庫、按表、按行。 這三個(gè)的對(duì)比中,并行度越來越大,額外損耗也是。無關(guān)大事務(wù)不會(huì)影響并發(fā)度。按照commit_id 的策略,適用范圍更廣,額外消耗也低。5.7的改進(jìn)策略并發(fā)性更優(yōu)。但出現(xiàn)大事務(wù)會(huì)拖后腿。
那么我們只有一實(shí)例只有一個(gè)database,這種情況下我們就只有拆庫拆表了:
對(duì)于這種情況下,我們可以選擇在應(yīng)用層做分庫分表,也可以選擇搞個(gè)中間層。不同的方案有不同的優(yōu)劣。
應(yīng)用層具有較好的性能,但是代碼耦合在業(yè)務(wù),如果后續(xù)擴(kuò)容還需該代碼,不能做到平滑擴(kuò)容拆分,假如有多個(gè)業(yè)務(wù)都需要實(shí)現(xiàn)同樣的功能,那么會(huì)帶來重復(fù)的工作量,而且工作難度也上升一個(gè)臺(tái)階。
中間件層具有較好的擴(kuò)展性,低耦合性,如果DB擴(kuò)容拆分,應(yīng)用可以做到無感知,無改動(dòng)。那么也有一些成熟的開源方案,比如MyCAT,Cobar,Atlas,kingshard等。
其次主從切換時(shí)帶來的復(fù)雜度較大,需要計(jì)算position或者重做從庫
一般情況下我們的MySQL都是一主多從架構(gòu),這樣既能給我們提供讀寫分離、負(fù)載均衡的便利,也能給我們提供容災(zāi)的能力。但是假如我們的主庫掛掉,這時(shí)我們會(huì)把從庫提升為主庫,但是在把從庫提升為新主的時(shí)候帶來了架構(gòu)的微變化。為了還能利用以上便利、提供容災(zāi)能力我們還得重新構(gòu)建這個(gè)新主的多個(gè)從庫。此時(shí)問題就來了,我們從庫必須知道我當(dāng)前應(yīng)該從Master 的那個(gè)位置開始復(fù)制,也就是說必須拿到Master的position 。為了拿到這個(gè)位置我們有兩種辦法,一種簡單粗暴,重做Slave;另一種是通過一些列復(fù)雜計(jì)算、補(bǔ)回差異數(shù)據(jù),算出當(dāng)前數(shù)據(jù)和新主數(shù)據(jù)的差異點(diǎn),從而得到新主庫position,導(dǎo)致HA切換和數(shù)據(jù)保護(hù)帶來巨大的挑戰(zhàn)。
MMM架構(gòu)(Master-Master replication manager for MySQL)
MMM是一套支持雙主故障切換和雙主日常管理的腳本程序,可以再主庫故障時(shí)保證熱備切換為新主庫,并且自動(dòng)的將從庫指向新主。但是這個(gè)架構(gòu)本身不能保證數(shù)據(jù)的一致性。
MHA架構(gòu)(Master High Availability)
MHA目前在MySQL高可用方面是一個(gè)相對(duì)成熟的解決方案,在自動(dòng)進(jìn)行故障切換的過程中,能最大程度上保證數(shù)據(jù)的一致性,以達(dá)到真正意義上的高可用。
那么HMA是如何最大程度保證數(shù)據(jù)一致的呢?當(dāng)主庫down掉時(shí),MHA試圖從宕機(jī)的主服務(wù)器上保存二進(jìn)制日志,最大程度的保證數(shù)據(jù)的不丟失,但這并不總是可行的。如果主庫發(fā)送down機(jī),日志會(huì)出現(xiàn)不同程度的丟失,有個(gè)解決辦法就是設(shè)置半同步復(fù)制。MHA在把從提升為主的過程中,會(huì)進(jìn)行一系列日志對(duì)比,找到最接近主庫的從庫提升為新主庫,把從庫間差異化的數(shù)據(jù)拿出來進(jìn)行應(yīng)用等等。
GTID?(Global Transaction ID)
在MySQL 5.6 以后官方引入了GTID,即在整個(gè)集群內(nèi)部,每個(gè)事務(wù)都有全局唯一的一個(gè)標(biāo)識(shí),這樣一來,當(dāng)我們主庫發(fā)送down掉,或者M(jìn)ySQL架構(gòu)有調(diào)整的時(shí)候,我們就不用很頭疼的去計(jì)算position;或者去配置略為復(fù)雜的MHA。我們只需要輕輕松松敲個(gè)CHANGE MASTER 命令帶上AUTO_POSITION就可以了,然后關(guān)于MASTER該從哪個(gè)binlog開始推送event給Slave這個(gè)完全由MySQL來幫我們計(jì)算。這個(gè)真是DBA們的福音啊。
簡單看看,為什么這么GTID這么神奇吧。在MySQL內(nèi)部幫我們記錄著 gtidpurged 和gtidexecuted 兩個(gè)集合。顧名思義,gtidexecuted 代表的時(shí)當(dāng)前已經(jīng)執(zhí)行過的GTID的集合;一般情況下我們binlog不可能永久保存,那么gtidpurged代表的就是當(dāng)前binlog已經(jīng)沒有的GTID集合,它是gtidexecuted的子集。我們知道在事務(wù)是不能跨binlog存在的,意味著每個(gè)binlog都會(huì)有一個(gè)完整的事務(wù)集合,同樣每個(gè)binlog文件的 header 部分,也都存放著這個(gè)binlog以前的 gtidexecuted 集合。我們的Slave 在應(yīng)用Binlog的時(shí)候都會(huì)記錄自己當(dāng)前已經(jīng)執(zhí)行過的最后一個(gè)事務(wù)GTID,那么我們?cè)谇袚Q主庫的時(shí)候,Slave就會(huì)把這個(gè)ID給帶上,然后Master端就會(huì)拿到這個(gè)GTID和自己當(dāng)前的gtidexecuted、gtidpurged 集合進(jìn)行對(duì)比,從而給到Slave一個(gè)合理的解釋。
OK,到這里MySQL從5.5的單線程復(fù)制,到5.6基于Schema級(jí)別的復(fù)制,再到5.7最大化還原主庫的并行就接近尾聲了。同時(shí)在這期間我們還給出了一些社區(qū)上、或者非技術(shù)上的解決方案。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的mysql 5.7变化_从MySQL 5.5到5.7看复制的演进的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: wxpython 按钮跳notebook
- 下一篇: linux cmake编译源码,linu