mysql源碼閱讀之半同步相關的簡單介紹

本文目錄一覽:

mysql半同步複製適合哪些業務場景呢

在允許更改操作繼續執行前,確保更改操作至少被寫入一個slave中的磁盤。也就是對於每一個連接,最多只有一個事務會由於master崩潰二丟失。半同步複製沒有暫停提交事務,只是在事務已被寫入到至少一個slave的中繼日誌中之前,避免發送一個答覆給客戶端。當slave被告知事務已經在持久存儲中之後,客戶端的提交才會返回。

mysql 異步複製和半同步複製

在MySQL5.5之前,MySQL 的複製是異步操作,主庫和從庫的數據之間存在一定的延遲,這樣存在一個隱患:當在主庫上寫入一個事務並提交成功,而從庫尚未得到主庫推送的Binlog日誌時,主庫宕機了,例如主庫可能因磁盤損壞、內存故障等造成主庫上該事務Binlog丟失,此時從庫就可能損失這個事務,從而造成主從不一致。

為了解決這個問題, MySQL5.5引人了半同步複製機制。

在MySQL 5.5之前的異步複製時,主庫執行完 Commit提交操作後,在主庫寫入 Binlog日誌後即可成功返回客戶端,無需等待Binlog日誌傳送給從庫,如圖31-7所示。

而半同步複製時,為了保證主庫上的每一個 Binlog 事務都能夠被可靠的複製到從庫上,主庫在每次事務成功提交時,並不及時反饋給前端應用用戶,而是等待其中一個從庫也接收到 Binlog事務並成功寫入中繼日誌後,主庫才返回Commit操作成功給客戶端。 半同步複製保證了事務成功提交後,至少有兩份日誌記錄 ,一份在主庫的 Binlog日誌上,另一份在至少一個從庫的中繼日誌Relay Log 上,從而更進一步保證了數據的完整性。半同步複製的大致流程如圖31-8所示。

半同步複製模式下,假如在圖31-8的步驟1、2、3中的任何一個步驟中主庫宕機,則事務並未提交成功,從庫上也沒有收到事務對應的 Binlog日誌,所以主從數據是一致的;

假如在步驟4傳送 Binlog日誌到從庫時,從庫宕機或者網絡故障,導致 Binlog並沒有及時地傳送到從庫上,此時主庫上的事務會等待一段時間(時間長短由參數rpl_semi_sync_master_timeout設置的毫秒數決定),如果 Binlog 在這段時間內都無法成功推送到從庫上,則 MySQL自動調整複製為異步模式,事務正常返回提交結果給客戶端。

半同步複製很大程度上取決於主從庫之間的網絡情況,往返時延RTT 越小決定了從庫的實時性越好。通俗地說,主從庫之間網絡越快,從庫越實時。

半同步模式是作為MySQL5.5的一個插件來實現的,主庫和從庫使用不同的插件。安裝比較簡單,在上一小節異步複製的環境上,安裝半同步複製插件即可。

1、首先,判斷MySQL服務器是否支持動態增加插件:

2、安裝插件

3、可以查看到已安裝的插件

4、在安裝完插件後,半同步複製默認是關閉的,這時需設置參數來開啟半同步

主:

從:

以上的啟動方式是在命令行操作,也可寫在配置文件中。

主:

從:

4、重啟從上的IO線程

從:

如果沒有重啟,則默認還是異步複製,重啟後,slave會在master上註冊為半同步複製的slave角色。這時候,主的error.log中會打印如下信息:

查看半同步是否在運行

主:

從:

這兩個變量常用來監控主從是否運行在半同步複製模式下。至此,MySQL半同步複製搭建完畢~

來做個實驗,觀察半同步狀態參數的變化。

1、在主庫上insert一條記錄,觀察下變化;

Rpl_semi_sync_master_net_waits加1,說明剛才的insert已經發送到從機並且主機還接收到從機的反饋響應;

2、我們將從機mysql停止,再次在主機上進行insert後查看狀態

可以看到,主機進行insert阻塞了10秒才返回結果。Rpl_semi_sync_master_status變為OFF,Rpl_semi_sync_master_no_tx加1,說明這條insert沒有同步到從機。後面再一次執行了insert立馬返回了結果,說明此時已經降級為異步複製;Rpl_semi_sync_master_no_tx也是增加了1;

3、現在恢復啟動從機,再次在主機上進行insert後查看狀態

Rpl_semi_sync_master_status還是OFF,Rpl_semi_sync_master_no_tx又增加了1。說明從庫重啟並不會自動恢復為原來的半同步複製,需要手動操作:

主 SET GLOBAL rpl_semi_sync_master_enabled = 1;

從 SET GLOBAL rpl_semi_sync_slave_enabled = 1; STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;

上面是從機重啟後的變化,那麼主到從之間的網絡問題呢,我們可以利用防火牆來模擬。

對於全同步複製,當主庫提交事務之後,所有的從庫節點必須收到,APPLY並且提交這些事務,然後主庫線程才能繼續做後續操作。這裡面有一個很明顯的缺點就是,主庫完成一個事務的時間被拉長,性能降低。

mysql主從複製原理,異步怎麼回事?半同步怎麼回事

研發的同事反饋,mysql的半同步怎麼變異步了?開始覺得不足為奇,超時之後,自然變成異步了。但同步binlog的速度變得正常之後,就會自動變成同步了。但抱着嚴謹負責的態度,馬上去檢查了一

下數據庫的日誌跟半同步的狀態。

看了一下從庫的錯誤日誌,被圖片中所示的sem-sync slave net_flush() reply failed 刷屏。。。。。。,汗了,這又是哪一出?  主庫卻沒有任何日誌。

雖然此時的主從同步的延遲時間是正常的,維持在0s的延遲,但此時同步狀態卻是異步的。

好奇怪呢?

查看一下代碼,該Semi-sync slave net_flush() reply failed 信息來自函數

ReplSemiSyncSlave::slaveReply,函數如下

 該錯誤發生的條件就是執行net_flush(net)函數,沒有收到正常的返回,報錯了,所以有上面的錯誤發生,該函數的作用是將從庫收到的binlog file 跟binlog pos的信息發送給主庫。

網絡有問題? 即使網路抖動性的問題,網路恢復之後應該正常才是。

為什麼這個錯誤持續刷屏? 而主從同步目前是正常的,只是由半同步變成了異步。

 當我將slave重啟之後,錯誤信息也很快就出現。

因為該函數是向主庫發送同步binlog的確認信息的,也就是ack信息,難道是主庫的ack的接收線程出了問題? 而主庫沒有任何的報錯信息 。

關鍵時刻,自己搞不定的時候,嘗試找幫手。我將錯誤信息,發給oracle公司的mysql開發者宋老師,宋老師是負責replication模塊的開發者,對replication相當熟悉,說我可能遇上一個mysql的Bug,讓我查看一下Bug 79865 .   在此,非常感謝宋老師的熱情的無償援助。

  bug 詳情鏈接: 

我們來看看採用了select()多路復用io模型的ack_reciver 線程的代碼:

bug的關鍵點是因為 ret= select(max_fd+1, fds, NULL, NULL, tv);  select()函數的入參max_fd+1有1024的限制,且這個限制無法通過修改nproc來突破?

(ulimit -n 命令可以修改nproc參數)。

貌似所有的疑問都揭開,但請繼續。

 作者採用的環境是5.7.15,同時,作者採用的操作系統是centOS 7,  根據上面 後半部分,Meiji Kimura 的描述信息,該bug在centos 6上復現了, 而在centOS7上沒有復現。而作者正是採用了centos 7.

怎麼判斷mysql是否是半同步複製

在談這個特性之前,我們先來看看mysql的複製架構衍生史。 MySQL的複製分為三種:         第一種,即普通的replication。 搭建簡單,使用非常廣泛,從mysql誕生之初,就產生了這種架構,性能非常好,可謂非常成熟。 但是這種架構數據是異步的,所以有丟失數據庫的風險。         第二種,即mysql cluster。 搭建也簡單,本身也比較穩定,是mysql裡面對數據保護最最靠譜的架構,也是唯一一個數據完全同步的架構,絕對的零丟失。不過性能就差遠些了。        第三種,即semi-sync replication,半同步,性能,功能都介於以上兩者之間。從mysql5.5開始誕生,目的是為了折中上述兩種架構的性能以及優缺點。“我們今天談論第三種架構

我們知道,普通的replication,也即mysql的異步複製,依靠mysql二進制日誌也即binary log進行數據複製。比如兩台機器,一台主機也即master,另外一台是從機,也即slave。

1. 正常的複製為:事務一(t1)寫入binlog buffer;dumper 線程通知slave有新的事務t1;binlog buffer 進行checkpoint;slave的io線程接收到t1並寫入到自己的的relay log;slave的sql線程寫入到本地數據庫。 這時,master和slave都能看到這條新的事務,即使master掛了,slave可以提升為新的master。          2. 異常的複製為:事務一(t1)寫入binlog buffer;dumper 線程通知slave有新的事務t1;binlog buffer 進行checkpoint;slave因為網絡不穩定,一直沒有收到t1;master 掛掉,slave提升為新的master,t1丟失。

3. 很大的問題是:主機和從機事務更新的不同步,就算是沒有網絡或者其他系統的異常,當業務並發上來時,slave因為要順序執行master批量事務,導致很大的延遲。

為了彌補以上幾種場景的不足,mysql從5.5開始推出了半同步。

即在master的dumper線程通知slave後,增加了一個ack,即是否成功收到t1的標誌碼。也就是dumper線程除了發送t1到slave,還承擔了接收slave的ack工作。如果出現異常,沒有收到ack,那麼將自動降級為普通的複製,直到異常修復。

我們可以看到半同步帶來的新問題:         1. 如果異常發生,會降級為普通的複製。 那麼從機出現數據不一致的幾率會減少,並不是完全消失。         2. 主機dumper線程承擔的工作變多了,這樣顯然會降低整個數據庫的性能。         3. 在MySQL 5.5和5.6使用after_commit的模式下,  即如果slave 沒有收到事務,也就是還沒有寫入到relay log 之前,網絡出現異常或者不穩定,此時剛好master掛了,系統切換到從機,兩邊的數據就會出現不一致。 在此情況下,slave會少一個事務的數據。

隨着MySQL 5.7版本的發布,半同步複製技術升級為全新的Loss-less Semi-Synchronous Replication架構,其成熟度、數據一致性與執行效率得到顯著的提升。

MySQL 5.7對數據複製效率進行了改進1 主從一致性加強支持在事務commit前等待ACK

新版本的semi sync 增加了rpl_semi_sync_master_wait_point參數 來控制半同步模式下 主庫在返回給會話事務成功之前提交事務的方式。

該參數有兩個值:

AFTER_COMMIT(5.6默認值)

master將每個事務寫入binlog ,傳遞到slave 刷新到磁盤(relay log),同時主庫提交事務。master等待slave 反饋收到relay log,只有收到ACK後master才將commit OK結果反饋給客戶端。

AFTER_SYNC(5.7默認值,但5.6中無此模式)

master 將每個事務寫入binlog , 傳遞到slave 刷新到磁盤(relay log)。master等待slave 反饋接收到relay log的ack之後,再提交事務並且返回commit OK結果給客戶端。 即使主庫crash,所有在主庫上已經提交的事務都能保證已經同步到slave的relay log中。

因此5.7引入了after_sync模式,帶來的主要收益是解決after_commit導致的master crash主從間數據不一致問題,因此在引入after_sync模式後,所有提交的數據已經都被複制,故障切換時數據一致性將得到提升。

2 性能提升支持發送binlog和接受ack的異步化

舊版本的semi sync 受限於dump thread ,原因是dump thread 承擔了兩份不同且又十分頻繁的任務:傳送binlog 給slave ,還需要等待slave反饋信息,而且這兩個任務是串行的,dump thread 必須等待 slave 返回之後才會傳送下一個 events 事務。dump thread 已然成為整個半同步提高性能的瓶頸。在高並發業務場景下,這樣的機制會影響數據庫整體的TPS .

圖:Without ACK receiving thread

為了解決上述問題,在5.7版本的semi sync 框架中,獨立出一個 ack collector thread ,專門用於接收slave 的反饋信息。這樣master 上有兩個線程獨立工作,可以同時發送binlog 到slave ,和接收slave的反饋。

圖:With ACK receiving thread3 性能提升控制主庫接收slave 寫事務成功反饋數量

MySQL 5.7新增了rpl_semi_sync_master_wait_slave_count參數,可以用來控制主庫接受多少個slave寫事務成功反饋,給高可用架構切換提供了靈活性。

如圖所示,當count值為2時,master需等待兩個slave的ack

4 性能提升

Binlog 互斥鎖改進

舊版本半同步複製在主提交binlog的寫會話和dump thread讀binlog的操作都會對binlog添加互斥鎖,導致binlog文件的讀寫是串行化的,存在並發度的問題。

MySQL 5.7對binlog lock進行了以下兩方面優化

1.移除了dump thread對binlog的互斥鎖

2.加入了安全邊際保證binlog的讀安全

5 性能提升組提交

5.7引入了新的變量slave-parallel-type,其可以配置的值有:

DATABASE (5.7之前默認值),基於庫的並行複製方式;LOGICAL_CLOCK (5.7新增值),基於組提交的並行複製方式;

MySQL 5.6版本也支持所謂的並行複製,但是其並行只是基於DATABASE的,也就是基於庫的。如果用戶的MySQL數據庫實例中存在多個DATABASE ,對於從機複製的速度的確可以有比較大的幫助,如果用戶實例僅有一個庫,那麼就無法實現並行回放,甚至性能會比原來的單線程更差。

MySQL5.7中增加了一種新的並行模式:為同時進入COMMIT階段的事務分配相同的序列號,這些擁有相同序列號的事務在備庫是可以並發執行的。

MySQL 5.7真正實現的並行複製,這其中最為主要的原因就是slave服務器的回放與主機是一致的即master服務器上是怎麼並行執行的slave上就怎樣進行並行回放。不再有庫的並行複製限制,對於二進制日誌格式也無特殊的要求(基於庫的並行複製也沒有要求)。

因此下面的序列中可以並發的序列為(其中前面一個數字為last_committed ,後面一個數字為sequence_number ):

trx1 1…..2trx2 1………….3trx3 1…………………….4trx4        2……………………….5trx5               3…………………………..6trx6                     3………………………………7trx7                            6………………………………..8

備庫並行規則:當分發一個事務時,其last_committed 序列號比當前正在執行的事務的最小sequence_number要小時,則允許執行。

因此,

a)trx1執行,last_commit2的可並發,trx2, trx3可繼續分發執行

b)trx1執行完成後,last_commit 3的可以執行, trx4可分發

c)trx2執行完成後,last_commit  4的可以執行, trx5, trx6可分發

d)trx3、trx4、trx5完成後,last_commit 7的可以執行,trx7可分發

綜上所述

我們認為MySQL 5.7版對Loss-Less半同步複製技術的優化,使得其成熟度和執行效率都得到了質的提高。我們建議在使用MySQL 5.7作為生產環境的部署時,可以使用半同步技術作為高可用與讀寫分離方案的數據複製方案。

請點擊輸入圖片描述

mysql的複製 半同步和同步的區別

異步複製(Asynchronous replication)

MySQL默認的複製即是異步的,主庫在執行完客戶端提交的事務後會立即將結果返給給客戶端,並不關心從庫是否已經接收並處理,這樣就會有一個問題,主如果crash掉了,此時主上已經提交的事務可能並沒有傳到從上,如果此時,強行將從提升為主,可能導致新主上的數據不完整。

全同步複製(Fully synchronous replication)

指當主庫執行完一個事務,所有的從庫都執行了該事務才返回給客戶端。因為需要等待所有從庫執行完該事務才能返回,所以全同步複製的性能必然會收到嚴重的影響。

半同步複製(Semisynchronous replication)

介於異步複製和全同步複製之間,主庫在執行完客戶端提交的事務後不是立刻返回給客戶端,而是等待至少一個從庫接收到並寫到relay log中才返回給客戶端。相對於異步複製,半同步複製提高了數據的安全性,同時它也造成了一定程度的延遲,這個延遲最少是一個TCP/IP往返的時間。所以,半同步複製最好在低延時的網絡中使用。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/297624.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-28 12:16
下一篇 2024-12-28 12:16

相關推薦

  • 如何修改mysql的端口號

    本文將介紹如何修改mysql的端口號,方便開發者根據實際需求配置對應端口號。 一、為什麼需要修改mysql端口號 默認情況下,mysql使用的端口號是3306。在某些情況下,我們需…

    編程 2025-04-29
  • Python簡單數學計算

    本文將從多個方面介紹Python的簡單數學計算,包括基礎運算符、函數、庫以及實際應用場景。 一、基礎運算符 Python提供了基礎的算術運算符,包括加(+)、減(-)、乘(*)、除…

    編程 2025-04-29
  • Python滿天星代碼:讓編程變得更加簡單

    本文將從多個方面詳細闡述Python滿天星代碼,為大家介紹它的優點以及如何在編程中使用。無論是剛剛接觸編程還是資深程序員,都能從中獲得一定的收穫。 一、簡介 Python滿天星代碼…

    編程 2025-04-29
  • 雲智直聘 源碼分析

    本文將會對雲智直聘的源碼進行分析,包括前端頁面和後端代碼,幫助讀者了解其架構、技術實現以及對一些常見的問題進行解決。通過本文的閱讀,讀者將會了解到雲智直聘的特點、優勢以及不足之處,…

    編程 2025-04-29
  • Python海龜代碼簡單畫圖

    本文將介紹如何使用Python的海龜庫進行簡單畫圖,並提供相關示例代碼。 一、基礎用法 使用Python的海龜庫,我們可以控制一個小海龜在窗口中移動,並利用它的“畫筆”在窗口中繪製…

    編程 2025-04-29
  • Python操作MySQL

    本文將從以下幾個方面對Python操作MySQL進行詳細闡述: 一、連接MySQL數據庫 在使用Python操作MySQL之前,我們需要先連接MySQL數據庫。在Python中,我…

    編程 2025-04-29
  • MySQL遞歸函數的用法

    本文將從多個方面對MySQL遞歸函數的用法做詳細的闡述,包括函數的定義、使用方法、示例及注意事項。 一、遞歸函數的定義 遞歸函數是指在函數內部調用自身的函數。MySQL提供了CRE…

    編程 2025-04-29
  • Python櫻花樹代碼簡單

    本文將對Python櫻花樹代碼進行詳細的闡述和講解,幫助讀者更好地理解該代碼的實現方法。 一、簡介 櫻花樹是一種圖形效果,它的實現方法比較簡單。Python中可以通過turtle這…

    編程 2025-04-28
  • MySQL bigint與long的區別

    本文將從數據類型定義、存儲空間、數據範圍、計算效率、應用場景五個方面詳細闡述MySQL bigint與long的區別。 一、數據類型定義 bigint在MySQL中是一種有符號的整…

    編程 2025-04-28
  • Python大神作品:讓編程變得更加簡單

    Python作為一種高級的解釋性編程語言,一直被廣泛地運用於各個領域,從Web開發、遊戲開發到人工智能,Python都扮演着重要的角色。Python的代碼簡潔明了,易於閱讀和維護,…

    編程 2025-04-28

發表回復

登錄後才能評論