日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Mysql主从复制(docker例子)

發(fā)布時間:2025/3/15 数据库 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Mysql主从复制(docker例子) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、Binlog

Binlog 日志主要作用是數(shù)據(jù)恢復和主從復制。本身就是二進制格式的日志文件,網(wǎng)絡(luò)傳輸無需進行協(xié)議轉(zhuǎn)換。MySQL 集群的高可用,負載均衡,讀寫分離等功能都是基于Binlog 來實現(xiàn)的。關(guān)于Binlog的文章

二、MySQL 主從復制主流架構(gòu)模型

我們基于 Binlog 可以復制出一臺 MySQL 服務器,也可以復制出多臺,取決于我們想實現(xiàn)什么功能。主流的系統(tǒng)架構(gòu)有如下幾種方式:

  • 一主一從 / 一主多從

    一主一從和一主多從是最常見的主從架構(gòu)方式,一般實現(xiàn)主從配置或者讀寫分離都可以采用這種架構(gòu)。如果是一主多從的模式,當 Slave 增加到一定數(shù)量時,Slave 對 Master 的負載以及網(wǎng)絡(luò)帶寬都會成為一個嚴重的問題。

  • 多主一從

    MySQL 5.7 開始支持多主一從的模式,將多個庫的數(shù)據(jù)備份到一個庫中存儲。

  • 雙主復制
    理論上跟主從一樣,但是兩個MySQL服務器互做對方的從,任何一方有變更,都會復制對方的數(shù)據(jù)到自己的數(shù)據(jù)庫。雙主適用于寫壓力比較大的業(yè)務場景,或者 DBA 做維護需要主從切換的場景,通過雙主架構(gòu)避免了重復搭建從庫的麻煩。(主從相互授權(quán)連接,讀取對方binlog日志并更新到本地數(shù)據(jù)庫的過程;只要對方數(shù)據(jù)改變,自己就跟著改變)

  • 級聯(lián)復制
    級聯(lián)模式下因為涉及到的 slave 節(jié)點很多,所以如果都連在 master 上對主服務器的壓力肯定是不小的。所以部分 slave 節(jié)點連接到它上一級的從節(jié)點上。這樣就緩解了主服務器的壓力。級聯(lián)復制解決了一主多從場景下多個從庫復制對主庫的壓力,帶來的弊端就是數(shù)據(jù)同步延遲比較大。

  • 企業(yè)級架構(gòu)

    海量用戶通過數(shù)據(jù)庫代理(mycat,shardingjdbc)訪問數(shù)據(jù)庫,然后數(shù)據(jù)庫讀寫分離,寫由master承擔,讀由slave承擔,同時,不同的業(yè)務場景可以指定特定的slave,降低數(shù)據(jù)庫并發(fā)量。同時,有兩個master(雙主復制,進行熱備份,需要keepalived等技術(shù)的支持),兩個互相同步,只要有一個master宕機,就提升另一個master為主master,而不是從slave中選舉。但是,這樣一個但master也無法突破數(shù)據(jù)量,那就得進行分庫分表了(進而將數(shù)據(jù)存在硬盤上),分完每一個分庫,又做成改圖得邏輯架構(gòu),從而提升mysql集群的可用性

  • 三、MySQL 主從復制原理

    MySQL 主從復制涉及到三個線程:

    • 一個在主節(jié)點的線程:log dump thread
    • 從庫會生成兩個線程:一個 I/O 線程,一個 SQL 線程

    如下圖所示:

  • 主庫會生成一個 log dump 線程,用來給從庫 I/O 線程傳 Binlog 數(shù)據(jù)。
  • 從庫的 I/O 線程會去請求主庫的 Binlog,并將得到的 Binlog 寫到本地的 relay log (中繼日志)文件中。
  • SQL 線程,會讀取 relay log 文件中的日志,并解析成 SQL 語句逐一執(zhí)行。
    • 主節(jié)點 log dump 線程
      當從節(jié)點連接主節(jié)點時,主節(jié)點會為其創(chuàng)建一個 log dump 線程,用于發(fā)送和讀取 Binlog 的內(nèi)容。在讀取 Binlog 中的操作時,log dump 線程會對主節(jié)點上的 Binlog 加鎖;當讀取完成發(fā)送給從節(jié)點之前,鎖會被釋放。主節(jié)點會為自己的每一個從節(jié)點創(chuàng)建一個 log dump 線程。

    • 從節(jié)點I/O線程
      當從節(jié)點上執(zhí)行start slave命令之后,從節(jié)點會創(chuàng)建一個 I/O 線程用來連接主節(jié)點,請求主庫中更新的Binlog。I/O 線程接收到主節(jié)點的 log dump 進程發(fā)來的更新之后,保存在本地 relay-log(中繼日志)中。

    • relay log
      這里又引申出一個新的日志概念。MySQL 進行主主復制或主從復制的時候會在要復制的服務器下面產(chǎn)生相應的 relay log。relay log 是怎么產(chǎn)生的呢?從服務器 I/O 線程將主服務器的 Binlog 日志讀取過來,解析到各類 Events 之后記錄到從服務器本地文件,這個文件就被稱為 relay log。然后 SQL 線程會讀取 relay log 日志的內(nèi)容并應用到從服務器,從而使從服務器和主服務器的數(shù)據(jù)保持一致。中繼日志充當緩沖區(qū),這樣 master 就不必等待 slave 執(zhí)行完成才發(fā)送下一個事件。

    四、relay log 相關(guān)參數(shù)查詢

    show variables like '%relay%';

  • max_relay_log_size
  • 標記 relay log 允許的最大值,如果該值為 0,則默認值為 max_binlog_size(1G);如果不為 0,則max_relay_log_size 則為最大的 relay_log 文件大小。

  • relay_log_purge
  • 是否自動清空不再需要中繼日志時。默認值為1(啟用)。

  • relay_log_recovery
  • 當 slave 從庫宕機后,假如 relay log 損壞了,導致一部分中繼日志沒有處理,則自動放棄所有未執(zhí)行的 relay log,并且重新從 master 上獲取日志,這樣就保證了 relay log 的完整性。默認情況下該功能是關(guān)閉的,將 relay_log_recovery 的值設(shè)置為 1 時,可在 slave 從庫上開啟該功能,建議開啟。

  • relay_log_space_limit
  • 防止中繼日志寫滿磁盤,這里設(shè)置中繼日志最大限額。但此設(shè)置存在主庫崩潰,從庫中繼日志不全的情況,不到萬不得已,不推薦使用。

  • sync_relay_log
  • 這個參數(shù)和 Binlog 中的 sync_binlog作用相同。當設(shè)置為 1 時,slave 的 I/O 線程每次接收到 master 發(fā)送過來的 Binlog 日志都要寫入系統(tǒng)緩沖區(qū),然后刷入 relay log 中繼日志里,這樣是最安全的,因為在崩潰的時候,你最多會丟失一個事務,但會造成磁盤的大量 I/O。當設(shè)置為 0 時,并不是馬上就刷入中繼日志里,而是由操作系統(tǒng)決定何時來寫入,雖然安全性降低了,但減少了大量的磁盤 I/O 操作。這個值默認是 0,可動態(tài)修改,建議采用默認值。

  • sync_relay_log_info
  • 當設(shè)置為 1 時,slave 的 I/O 線程每次接收到 master 發(fā)送過來的 Binlog 日志都要寫入系統(tǒng)緩沖區(qū),然后刷入 relay-log.info 里,這樣是最安全的,因為在崩潰的時候,你最多會丟失一個事務,但會造成磁盤的大量 I/O。當設(shè)置為 0 時,并不是馬上就刷入 relay-log.info 里,而是由操作系統(tǒng)決定何時來寫入,雖然安全性降低了,但減少了大量的磁盤 I/O 操作。這個值默認是0,可動態(tài)修改,建議采用默認值。

    五、從節(jié)點 SQL 線程

    SQL 線程負責讀取 relay log 中的內(nèi)容,解析成具體的操作并執(zhí)行,最終保證主從數(shù)據(jù)的一致性。對于每一個主從連接,都需要這三個進程來完成。當主節(jié)點有多個從節(jié)點時,主節(jié)點會為每一個當前連接的從節(jié)點建一個 log dump 進程,而每個從節(jié)點都有自己的 I/O 進程,SQL 進程。從節(jié)點用兩個線程將從主庫拉取更新和執(zhí)行分成獨立的任務,這樣在執(zhí)行同步數(shù)據(jù)任務的時候,不會降低讀操作的性能。比如,如果從節(jié)點沒有運行,此時 I/O 進程可以很快從主節(jié)點獲取更新,盡管 SQL 進程還沒有執(zhí)行。如果在 SQL 進程執(zhí)行之前從節(jié)點服務停止,至少 I/O 進程已經(jīng)從主節(jié)點拉取到了最新的變更并且保存在本地 relay log 中,當服務再次起來之后就可以完成數(shù)據(jù)的同步。要實施復制,首先必須打開 Master 端的 Binlog 功能,否則無法實現(xiàn)。因為整個復制過程實際上就是 Slave 從 Master 端獲取該日志然后再在自己身上完全順序的執(zhí)行日志中所記錄的各種操作。如下圖所示:

    六、數(shù)據(jù)復制的基本過程

  • 在從節(jié)點上執(zhí)行 sart slave 命令開啟主從復制開關(guān),開始進行主從復制。從節(jié)點上的 I/O 進程連接主節(jié)點,并請求從指定日志文件的指定位置(或者從最開始的日志)之后的日志內(nèi)容。
  • 主節(jié)點接收到來自從節(jié)點的 I/O 請求后,通過負責復制的 I/O 進程(log Dump Thread)根據(jù)請求信息讀取指定日志指定位置之后的日志信息,返回給從節(jié)點。返回信息中除了日志所包含的信息之外,還包括本次返回的信息的 Binlog file 以及 Binlog position(Binlog 下一個數(shù)據(jù)讀取位置)。
  • 從節(jié)點的 I/O 進程接收到主節(jié)點發(fā)送過來的日志內(nèi)容、日志文件及位置點后,將接收到的日志內(nèi)容更新到本機的 relay log 文件(Mysql-relay-bin.xxx)的最末端,并將讀取到的 Binlog文件名和位置保存到master-info 文件中,以便在下一次讀取的時候能夠清楚的告訴 Master :“ 我需要從哪個 Binlog 的哪個位置開始往后的日志內(nèi)容,請發(fā)給我”。
  • Slave 的 SQL 線程檢測到relay log 中新增加了內(nèi)容后,會將 relay log 的內(nèi)容解析成在能夠執(zhí)行 SQL 語句,然后在本數(shù)據(jù)庫中按照解析出來的順序執(zhí)行,并在 relay log.info 中記錄當前應用中繼日志的文件名和位置點。
  • 七、MySQL 基于 Binlog 主從復制的模式介紹

    MySQL 主從復制默認是異步的模式。MySQL增刪改操作會全部記錄在 Binlog 中,當 slave 節(jié)點連接 master 時,會主動從 master 處獲取最新的 Binlog 文件。并把 Binlog 存儲到本地的 relay log 中,然后去執(zhí)行 relay log 的更新內(nèi)容。

    • 異步模式 (async-mode)

    異步模式如下圖所示:

    這種模式下,主節(jié)點不會主動推送數(shù)據(jù)到從節(jié)點,主庫在執(zhí)行完客戶端提交的事務后會立即將結(jié)果返給給客戶端,并不關(guān)心從庫是否已經(jīng)接收并處理,這樣就會有一個問題,主節(jié)點如果崩潰掉了,此時主節(jié)點上已經(jīng)提交的事務可能并沒有傳到從節(jié)點上,如果此時,強行將從提升為主,可能導致新主節(jié)點上的數(shù)據(jù)不完整。

    • 半同步模式(semi-sync)

    介于異步復制和全同步復制之間,主庫在執(zhí)行完客戶端提交的事務后不是立刻返回給客戶端,而是等待至少一個從庫接收到并寫到 relay log 中才返回成功信息給客戶端(只能保證主庫的 Binlog 至少傳輸?shù)搅艘粋€從節(jié)點上),否則需要等待直到超時時間然后切換成異步模式再提交。

    相對于異步復制,半同步復制提高了數(shù)據(jù)的安全性,一定程度的保證了數(shù)據(jù)能成功備份到從庫,同時它也造成了一定程度的延遲,但是比全同步模式延遲要低,這個延遲最少是一個 TCP/IP 往返的時間。所以,半同步復制最好在低延時的網(wǎng)絡(luò)中使用。半同步模式不是 MySQL 內(nèi)置的,從 MySQL 5.5 開始集成,需要 master 和 slave 安裝插件開啟半同步模式。

    • 全同步模式

    指當主庫執(zhí)行完一個事務,然后所有的從庫都復制了該事務并成功執(zhí)行完才返回成功信息給客戶端。因為需要等待所有從庫執(zhí)行完該事務才能返回成功信息,所以全同步復制的性能必然會收到嚴重的影響。

    八、基于docker搭建Mysql主從復制例子

  • 下載mysql8.0版本
  • docker pull mysql:8.0
  • 創(chuàng)建如下目錄用于掛載
    • mydata/mysql/master
      master下編寫my.conf
    • mydata/mysql/slave-1
      slave-1下編寫my-slave-1.cnf
    • mydata/mysql/slave-2
      slave-2下編寫my-slave-2.cnf

    my.conf內(nèi)容如下

    [mysqld] user=mysql character-set-server=utf8 default_authentication_plugin=mysql_native_password secure_file_priv=/var/lib/mysql expire_logs_days=7 sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION max_connections=1000[client] default-character-set=utf8[mysql] default-character-set=utf8

    參考文章

  • 執(zhí)行容器命令如下
  • docker run \ --restart=always \ --privileged=true \ -p 13306:3306 --name mysql-master \ -v /mydata/mysql/master/log:/var/log/mysql \ -v /mydata/mysql/master/data:/var/lib/mysql \ -v /mydata/mysql/master/my.cnf:/etc/mysql/my.cnf \ -v /mydata/mysql/master/conf.d:/etc/mysql/conf.d \ -e MYSQL_ROOT_PASSWORD=root \ -d mysql:8.0------------------------------------------------------------- docker run \ --restart=always \ --privileged=true \ -p 23306:3306 --name mysql-slave-1 \ -v /mydata/mysql/slave-1/log:/var/log/mysql \ -v /mydata/mysql/slave-1/data:/var/lib/mysql \ -v /mydata/mysql/slave-1/my-slave-1.cnf:/etc/mysql/my.cnf \ -v /mydata/mysql/slave-1/conf.d:/etc/mysql/conf.d \ -e MYSQL_ROOT_PASSWORD=root \ -d mysql:8.0-------------------------------------------- docker run \ --restart=always \ --privileged=true \ -p 33306:3306 --name mysql-slave-2 \ -v /mydata/mysql/slave-2/log:/var/log/mysql \ -v /mydata/mysql/slave-2/data:/var/lib/mysql \ -v /mydata/mysql/slave-2/my-slave-2.cnf:/etc/mysql/my.cnf \ -v /mydata/mysql/slave-2/conf.d:/etc/mysql/conf.d \ -e MYSQL_ROOT_PASSWORD=root \ -d mysql:8.0

  • master主從復制配置
  • 在my.cnf中添加以下配置,注意添加到[mysqld]下面

    #服務器id 留心各自的server-id一定要彼此獨立,不能重復,否則,會出現(xiàn)如下錯誤: #Slave: received end packet FROM server, apparent master shutdown server_id=1#bing二進制日志文件 log-bin=mysql-bin#是否只讀 read-only=0#要同步的數(shù)據(jù)庫 binlog-do-db=test#不同步的數(shù)據(jù)庫 binlog-ignore-db=ignore#以下是每個數(shù)據(jù)庫都會自帶的數(shù)據(jù)庫,不需要復制 replicate-ignore-db=mysql replicate-ignore-db=sys replicate-ignore-db=information_schema replicate-ignore-db=performance_schema

    也分別在my-slave-1.cnf、my-slave-2.cnf配置以上信息(注意修改server_id),并重啟docker

  • 讓master授權(quán)某一用戶,讓其他slave可以來同步master的數(shù)據(jù)
  • 注意這里,8.0版本的mysql已經(jīng)將用戶的創(chuàng)建和授權(quán)分開了。

    - CREATE USER 'backup'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; - GRANT REPLICATION SLAVE ON *.* TO 'backup'@'%';
  • 讓兩臺slave追尋主master
  • CHANGE MASTER TO MASTER_HOST='172.17.0.6',MASTER_USER='backup',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=0,MASTER_PORT=3306;

    這里一定要注意:由于我3個mysql都是基于docker的虛擬網(wǎng)絡(luò)的,所以這里的MASTER_PORT不是暴露給外網(wǎng)的13306,而是基于docker局域網(wǎng)內(nèi)的3306,如果遇到Slave_IO_Running:Connecting ; Slave_SQL_Running:Yes的問題,參考這兩篇文章一定能解決,文章1,文章2。
    注意這里的host不是簡單的localhost,而是docker分配的

    • 啟動同步:
    start slave

    • 關(guān)閉同步
    stop slave

    至此,mysql主從同步搭建完成


    可以看到master中的test同步到了slave中,而ignore則沒有

    九、主從復制可能會出現(xiàn)的問題

  • Slave 同步延遲
  • 因為 Slave 端是通過 I/O thread 單線程來實現(xiàn)數(shù)據(jù)解析入庫;而 Master 端寫 Binlog 由于是順序?qū)懶屎芨?#xff0c;當主庫的 TPS 很高的時候,必然 Master 端的寫效率要高過 Slave 端的讀效率,這時候就有同步延遲的問題。I/O Thread 的同步是基于庫的,即同步幾個庫就會開啟幾個 I/O Thread。可以通過 show slave status 命令查看 Seconds_Behind_Master 的值來看是否出現(xiàn)同步延遲,這個值代表主從同步延遲的時間,值越大說明延遲越嚴重。值為 0 為正常情況,正值表示已經(jīng)出現(xiàn)延遲,數(shù)字越大從庫落后主庫越多。基于 Binlog 的復制方式肯定有這種問題,MySQL 官方也意識到,單線程不如多線程強,所以在 MySQL 5.7 版本引入了基于組提交的并行復制(官方稱為Enhanced Multi-threaded Slaves,即MTS),設(shè)置參數(shù):slave_parallel_workers>0 即可,并且 global.slave_parallel_type=‘LOGICAL_CLOCK’,即可支持一個 schema(庫) 下,slave_parallel_workers個 worker 線程并發(fā)執(zhí)行 relay log 中主庫提交的事務。

  • 其核心思想:
  • 一個組提交的事務都是可以并行回放(配合binary log group commit);slave 機器的 relay log 中 last_committed 相同的事務(sequence_num不同)可以并發(fā)執(zhí)行。其中,變量 slave-parallel-type 可以有兩個值:

    • DATABASE 默認值,基于庫的并行復制方式
    • LOGICAL_CLOCK,基于組提交的并行復制方式

    MySQL 5.7 開啟 MTS 很簡單,只需要在 Slave 從數(shù)據(jù)庫的 my.cnf 文件中如下配置即可:

    # slaveslave-parallel-type=LOGICAL_CLOCKslave-parallel-workers=8 #一般建議設(shè)置4-8,太多的線程會增加線程之間的同步開銷master_info_repository=TABLErelay_log_info_repository=TABLErelay_log_recovery=ON

    當然多線程帶來的并行復制方案也有很多實現(xiàn)難點,比如事務都是有序執(zhí)行的,如果并行回放會不會存在執(zhí)行數(shù)據(jù)錯亂的問題。這些問題就不在本節(jié)解釋,大家有興趣可以繼續(xù)深究。

    參考文章

    總結(jié)

    以上是生活随笔為你收集整理的Mysql主从复制(docker例子)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。