mysql半同步(semi-sync)源碼實現

来源:http://www.cnblogs.com/cchust/archive/2016/01/05/5093965.html
-Advertisement-
Play Games

mysql複製簡單介紹了mysql semi-sync的出現的原因,並說明瞭semi-sync如何保證不丟數據。這篇文章主要側重於semi-sync的實現,結合源碼將semi-sync的實現過程展現給大家。最新的semi-sync源碼可以參考官方5.7版本的實現,https://github....


      mysql複製簡單介紹了mysql semi-sync的出現的原因,並說明瞭semi-sync如何保證不丟數據。這篇文章主要側重於semi-sync的實現,結合源碼將semi-sync的實現過程展現給大家。最新的semi-sync源碼可以參考官方5.7版本的實現,https://github.com/mysql/mysql-server

打開semi-sync的正確姿勢
     預設情況下的mysql複製都是非同步複製,mysql通過參數來控制semi-sync開關。具體而言,主庫上通過rpl_semi_sync_master_enabled參數控制,備庫上通過rpl_semi_sync_slave_enabled參數控制,打開這兩個參數後,mysql semi-sync的特性就打開了。註意對於備庫而言,為了保證半同步立即生效,需要重啟slave的IO線程。另外,還有一個比較重要的參數是rpl_semi_sync_master_timeout,這個參數用於控制master等待semi-slave ack報文的時間,單位是毫秒,預設是10000。master等待超時,則切換為普通的非同步複製。

master:
set global rpl_semi_sync_master_enabled=1;
set global rpl_semi_sync_master_timeout=xxx;

slave:
stop slave io_thread;
set global rpl_semi_sync_slave_enabled=1;
start slave io_thread;

另外需要註意的是,打開了上述兩個參數只說明master-slave已經具備打開semi-sync的基本條件了,但複製是否依照半同步運行,還需要根據Rpl_semi_sync_master_status的狀態值確定。因為比如slave較master有很大延遲(超過rpl_semi_sync_master_timeout),那麼複製切換為普通複製。對於需要調試代碼的童鞋而言,rpl_semi_sync_master_trace_level和rpl_semi_sync_slave_trace_level非常重要,通過設置level取值,可以列印日誌記錄半同步的詳細過程,方便定位問題。

semi-sync的實現
semi-sync說到底也是一種複製,只不過是在普通的複製基礎上,添加了一些步驟來實現。因此semi-sync並沒有改變複製的基本框架,我們的討論也從master,slave兩方面展開。
1.master(主庫)

主庫上面主要包含三個部分,(1).負責與slave-io線程對接的binlog dump線程,將binlog發送到slave,(2).主庫上寫事務的工作線程,(3).收取semi-slave報文的ack_receiver線程。

(1).binlog dump流程
主要執行邏輯在mysql_binlog_send函數中。

1.判斷slave是否是semi_slave,調用add_slave將semi-slave加入到ack_receiver線程的監聽隊列中。判斷的邏輯是slave對應的會話上是否設置了參數rpl_semi_sync_slave。

2.根據slave的請求偏移和binlog文件,從指定位點讀取binlog
3.根據文件和位點,撈binlog文件中的數據
4.調用updateSyncHeader設置數據包頭semi-sync標記
根據實時semi-sync運行狀態來確定是否設置(這個狀態由ack_receiver線程根據是否及時收到slave-ack報文設置)
5.調用my_net_write發送binlog
6.調用net_flush確認網路包發送出去
如果當前所有產生的binlog已經處理完,需調用wait_for_update_bin_log等待binlog更新。

(2).半同步事務提交流程
mysql5.6以後提交採用組提交方式,主要分為三個階段,每個階段有一個隊列,增加semi-sync後,又增加了一個semi-sync階段。
1.flush階段:
隊列能保證寫binlog的順序與innodb-commit的順序一致。通過隊列,可以保證順序寫每個事務的binlog-cache,然後只進行一次write操作(flush_cache_to_file)。flush階段後,如果sync_binlog不是1,則通知master有新binlog產生;如果sync_binlog為1,則等待sync階段後,再通知dump線程有新binlog產生。這裡我理解是因為如果不為1,則可能沒有後續的sync階段,而操作系統緩存也有binlog數據,所以可以在flush階段後通知;而對於sync_binlog為1的情況,可以保證主庫的binlog先落地,永遠比備庫多。但如果sync_binlog不為1,比如1000,則主機異常情況下,則可能出現備庫的binlog比主庫還多的情況。根據sync_binlog的設置,確認是否要跳過sync階段。
2.sync階段:
sync_binlog_file
3.semi_sync階段:
call_after_sync,等待備庫應答。調用cond_timewait等待條件變數&COND_binlog_send_
4.commit階段:
innodb-commit
waitAfterCommit,等待備庫應答。調用cond_timewait等待條件變數&COND_binlog_send_ 。最終我們根據semi-sync複製模式的設置(AFTER_COMMIT,AFTER_SYNC),來確定是第(3)步還是第(4)步進行等待。

(3).接收slave-ack報文流程
這個流程的工作主要在ack_receiver線程中,這個線程的主要作用是監聽semi-slave的ack包,確認master-slave鏈路是否工作在半同步狀態,並根據實際運行狀態將普通複製與半同步複製進行切換。打開主庫rpl_semi_sync_master_enabled參數後,該線程啟動,關閉參數後,該線程消亡。
流程如下:
1.遍歷semi-slave數組
2.通過select函數監聽每個slave是否有網路包過來
3.調用my_net_read讀取包數據
4.調用reportReplyPacket處理semi-sync複製狀態
若備庫已經獲取了最新的binlog位點,則喚醒等待的工作線程
5.調用reportReplyBinlog喚醒等待的線程,mysql_cond_broadcast(&COND_binlog_send_);

2.slave(備庫)

主要實現在(handle_slave_io)
1.啟動io-thread後,調用safe_connect建立與master的連接
2.調用request_dump函數處理請求binlog邏輯
(1).執行命令SET @rpl_semi_sync_slave= 1,設置一個局部變數,通過這個參數標記slave為semi-slave
(2).發送命令COM_BINLOG_DUMP請求日誌
迴圈從master端收取日誌,處理日誌
{
  1.調用read_event,從master端收取日誌(如果沒有網路包,會阻塞等待)
  2.調用slaveReadSyncHeader,確定網路包頭是否有semi-sync標記
  3.調用queue_event將日誌寫入relay-log,在這個過程中會過濾自身server-id的日誌
  4.如果有semi-sync標記,調用slaveReply函數,發送ack報文
}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文通過java代碼使用jdbc連接hive,詳細解釋了其操作步驟與問題,適用於hive1.2版本
  • 今天Linux伺服器機子重啟了下,Oracle啟動不起來,提示:解決ORA-00824: cannot set sga_target due to existing看了很多解決方法,發現下麵這個特別好,特別簡單轉:http://blog.chinaunix.net/uid-22448653-id-3...
  • 統計分析中Type I Error與Type II Error的區別 ============== 在統計分析中,經常提到Type I Error和Type II Error。他們的基本概念是什麼?有什麼區別? 下麵的表格顯示 between truth/falseness of the null ...
  • 實體類:using MongoDB.Bson;namespace WindowsFormsApp{ class User { //public ObjectId _id; //BsonType.ObjectId 這個對應了 MongoDB.Bson.ObjectId ...
  • 一、業務場景我們在實際生產環境中遇到了這樣一種需求,即需要檢索一個父子關係的子樹數據估計大家也遇到過類似的場景,最典型的就是省市數據,其中path欄位是按層級關係生成的行政區路徑:如果我們已知某市名,想查出同級和高一級的省名,如保定市同級和上級河北省,那麼我們有什麼實現方式呢給大家10秒鐘,快速搶答...
  • SQL Server無法收縮日誌文件 2 因為邏輯日誌文件的總數不能少於 2問題最近伺服器執行收縮日誌文件大小的job老是報錯我所用的一個批量收縮日誌腳本USE [master]GO/****** Object: StoredProcedure [dbo].[ShrinkUser_DATABASE....
  • 標簽:主從概述本篇文章主要介紹mysql主從的搭建過程和中間涉及的一些概念知識,希望能最全面的將mysql主從所涉及到的知識都概況進來;環境已經安裝好了mysql,這裡就不介紹mysql的安裝方法。測試環境:主:mysql(5.6.21),linux:redhat 6.0,ip:192.168.1....
  • 1.問題背景 預設情況下,線上的mysql複製都是非同步複製,因此在極端情況下,主備切換時,會有一定的概率備庫比主庫數據少,因此切換後,我們會通過工具進行回滾回補,確保數據不丟失。半同步複製則要求主庫執行每一個事務,都要求至少一個備庫成功接收後,才真正執行完成,因此可以保持主備庫的強一致性。為了確.....
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...