MySQL主從復制:半同步、異步

        MySQL主從復制:半同步、異步


mysql

    前言

    本篇我們介紹MySQL Replication的相關內容, 我們首先介紹MySQL CLuster的實現原理和如何一步步構建一個MySQL Replication Cluster

    看懂本文需要了解: MySQL基本操作,MySQL日志類型及其作用

    如何對MySQL進行擴展?

    大家之前應該了解; 在單臺服務器性能不足時, 有兩種方式進行擴展

    • Scale Up ; 垂直擴展

    • Scale Out ; 水平擴展

      垂直擴展: 指的是提升單臺服務器的性能(硬件)來提升服務的性能 
      水平擴展: 指的是添加服務器通過負載均衡的方式來分擔單臺服務器的負載, 從而提升服務的性能

    我們可以通過LVS, HAProxy, Nginx等軟件實現一些服務的負載均衡, 但是如果要用到MySQL上就會有一些問題, 如下

    • 如何保證多臺MySQL服務器數據的一致性

    • 如何保證多臺服務器同時提交事務導致數據的完整性

    • 如何保證一臺服務器宕機時, 其的事務能夠正常提交或ROLLBACK

    我們需要考慮的問題比擴展WEB服務多太多了, 畢竟大家都知道, 數據無價, 在很多重要場景中, 數據不能有半點閃失, 但是MySQL對這方面做得并不是很好, 而Oracle數據庫在這方面特別的厲害, 所以眾多的銀行都采用Oracle數據庫存儲客戶的賬戶信息等, 這么說, 難道我們就不用MySQL了么? 這顯然不可能, 我們首先來介紹一下MySQL Replication Cluster的幾種同步數據方式

    • Synchronous Replication 同步復制

    • Asynchronous Replication 異步復制

    • Semisynchronous Replication 半同步復制

      同步復制: 指的是客戶端連接到MySQL主服務器寫入一段數據, MySQL主服務器同步給MySQL從服務器需要等待從服務器發出同步完成的響應才返回客戶端OK, 這其中等待同步的過程是阻塞的, 如果有N臺從服務器, 效率極低 
      異步復制: 指的是客戶端連接到
      MySQL主服務器寫入一段數據, MySQL主服務器將寫入的數據發送給MySQL從服務器, 然后直接返回客戶端OK, 可能從服務器的數據會和主服務不一致 
      半同步復制:指的是客戶端連接到
      MySQL主服務器寫入一段數據, MySQL主服務器只將數據同步復制給其中一臺從服務器, 半同步復制給其他的從服務器, 來達到其中一臺從服務器完全同步的效果

    MySQL Replication WorkFlow

    Master/Slave工作流程

    blob.png

    建立主從關系后, 主服務器如果有數據修改之后, BINLOG會更新, 從服務通過IO-Thread讀取主服務器的BINLOG到本地的Relay Log, 再通過SQL-Thread對其進行重放(replay), 從而同步到本地

    MySQL主從復制模式

    在不同的業務模型中我們可以采用不同的MySQL主從復制架構, 一般分為以下兩種

    • Master/Slave

    • Master/Master

      Master/Slave: 指的是一主多從模式, 這種模式下可以有效的分擔讀請求, 但是寫請求并不能完成負載分擔、從節點可能數據不一致, 并且如果Master宕機了客戶端就無法進行寫操作了, 還是有很多問題的 
      Master/Master: 指的是多主模式, 這種模式中的多臺
      MySQL服務器都是Master, 也就意味著都可以進行讀寫操作, 但是有著更為嚴重的問題, 多個客戶端同時寫入數據時由于復制延遲可能到導致數據沖突等嚴重問題

    常用的架構圖

    我們可以使用keepalived實現Master高可用, 并且使用半同步模式實現數據的完全同步

    blob.png

    上面那種方式太占用Master的帶寬, 我們可以讓一臺Slave扮演為Master, 為其他Slave同步數據

    blob.png

    實戰演練

    MySQL異步復制實現

    實驗拓撲

    blob.png

    環境部署

    我們需要在各臺服務器上安裝MySQL, 這里使用的是rpm包安裝, 版本為5.1

    [root@node1 ~]# yum install mysql-server -y
    [root@node2 ~]# yum install mysql-server -y
    [root@node3 ~]# yum install mysql-server -y

    配置文件

    node1配置文件(master)

       [mysqld]
       datadir=/var/lib/mysql
       socket=/var/lib/mysql/mysql.sock
       user=mysql
       # Disabling symbolic-links is recommended to prevent assorted security risks
       symbolic-links=0
       innodb_file_per_table = 1
       log_bin=master-log    #開啟二進制日志
       log_bin_index=1
       server_id=1           #設置serverid

       [mysqld_safe]
       log-error=/var/log/mysqld.log
       pid-file=/var/run/mysqld/mysqld.pid

    node2配置文件(slave1)

       [mysqld]
       datadir=/var/lib/mysql
       socket=/var/lib/mysql/mysql.sock
       user=mysql
       # Disabling symbolic-links is recommended to prevent assorted security risks
       symbolic-links=0
       relay-log=relay-log         #開啟relay日志
       innodb_file_per_table = 1
       read-only = 1               #設置只讀
       server_id = 2               #設置serverid

       [mysqld_safe]
       log-error=/var/log/mysqld.log
       pid-file=/var/run/mysqld/mysqld.pid

    node3配置文件(slave2)

       [mysqld]
       datadir=/var/lib/mysql
       socket=/var/lib/mysql/mysql.sock
       user=mysql
       # Disabling symbolic-links is recommended to prevent assorted security risks
       symbolic-links=0
       relay-log=relay-log
       innodb_file_per_table = 1
       read-only = 1
       server_id = 3

       [mysqld_safe]
       log-error=/var/log/mysqld.log
       pid-file=/var/run/mysqld/mysqld.pid


    ##啟動mysql
    ##注意: serverid一定不能相同

    配置Master

    Slave節點進行同步需要通過一個特定的用戶進行, 所以我們需要創建一個用戶并賦予REPLICATION SLAVE, REPLICATION CLIENT權限

    mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'rpuser'@'%' IDENTIFIED BY 'passwd';
    Query OK, 0 rows affected (0.00 sec)

    mysql> FLUSH PRIVILEGES;
    Query OK, 0 rows affected (0.00 sec)

    mysql> SHOW MASTER STATUS;   我們要記錄下pos的數值
    +-------------------+----------+--------------+------------------+

    | File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +-------------------+----------+--------------+------------------+

    | master-log.000005 |      523 |              |                  |
    +-------------------+----------+--------------+------------------+

    1 row in set (0.00 sec)

    配置Slave(1)

    mysql> CHANGE MASTER TO
       -> MASTER_HOST='172.16.1.2',
       -> MASTER_USER='rpuser',
       -> MASTER_PASSWORD='passwd',
       -> MASTER_LOG_FILE='master-log.000005',
       -> MASTER_LOG_POS=523;
    Query OK, 0 rows affected (0.01 sec

    mysql> SHOW SLAVE STATUS\G;  #查看相應信息
    #########省略##################
    Master_Log_File: master-log.000005
    Read_Master_Log_Pos: 523
    Relay_Log_File: relay-log.000001
    Relay_Log_Pos: 4
    Relay_Master_Log_File: master-log.000005
    Slave_IO_Running: No    #IO-thread沒有啟動
    Slave_SQL_Running: No   #SQL-thread沒有啟動
    ###
    ######省略##################

    mysql> START SLAVE;  #啟動sql-thread和io-thred

    mysql> SHOW SLAVE STATUS\G;  #查看相應信息
    Query OK, 0 rows affected (0.00 sec)
    #########省略##################
    Master_Log_File: master-log.000005
    Read_Master_Log_Pos: 523
    Relay_Log_File: relay-log.000002
    Relay_Log_Pos: 252
    Relay_Master_Log_File: master-log.000005
    Slave_IO_Running: Yes     #IO-thread啟動
    Slave_SQL_Running: Yes    #SQL-thread啟動
    ###
    ######省略##################

    配置slave(2)

    過程和配置slave(1)相同, 不做演示

    測試主從復制


    ##在主服務器上創建數據庫和表

    [root@node1 ~]# mysql

    mysql> SHOW DATABASES;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | test               |
    +--------------------+
    3 rows in set (0.00 sec)

    mysql> CREATE DATABASE replication;

    Query OK, 1 row affected (0.00 sec)

    mysql> USE replication;
    Database changed
    mysql> CREATE TABLE t1 (id int unsigned auto_increment primary key, name char(30));
    Query OK, 0 rows affected (0.01 sec)

    mysql> DESC t1;
    +-------+------------------+------+-----+---------+----------------+
    | Field | Type             | Null | Key | Default | Extra          |
    +-------+------------------+------+-----+---------+----------------+
    | id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
    | name  | char(30)         | YES  |     | NULL    |                |
    +-------+------------------+------+-----+---------+----------------+
    2 rows in set (0.00 sec)

    mysql> SHOW MASTER STATUS;

    +-------------------+----------+--------------+------------------+
    | File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +-------------------+----------+--------------+------------------+
    | master-log.000005 |      765 |              |                  |
    +-------------------+----------+--------------+------------------+
    1 row in set (0.00 sec)
    ##在slave服務器測試

    [root@node2 ~]# mysql

    mysql> SHOW DATABASES;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | replication        |
    | test               |
    +--------------------+
    4 rows in set (0.00 sec)

    mysql> use replication;

    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A

    Database changed
    mysql> DESC t1;
    +-------+------------------+------+-----+---------+----------------+
    | Field | Type             | Null | Key | Default | Extra          |
    +-------+------------------+------+-----+---------+----------------+
    | id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
    | name  | char(30)         | YES  |     | NULL    |                |
    +-------+------------------+------+-----+---------+----------------+
    2 rows in set (0.00 sec)

    mysql> SHOW SLAVE STATUS\G;


    #########省略##################
    Master_Log_File: master-log.000005
    Read_Master_Log_Pos: 765   #已經同步
    Relay_Log_File: relay-log.000002
    Relay_Log_Pos: 494
    Relay_Master_Log_File: master-log.000005
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
    #########省略##################

    MySQL半同步復制實現

    由于MySQL半同步復制在MySQL5.5以后才以插件的形式進行提供, 所以這里我們的MySQL要換成5.5版本的MariaDB

    由于很多步驟和上面重復,我就不寫出來了,先配置成M/S然后再按照我下面操作

    實驗拓撲

    blob.png

    配置master

    半同步的插件在/usr/lib64/mysql/plugin下, master用的semisync_master.so,slave用的semisync_slave.so,

    MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
    Query OK, 0 rows affected (0.00 sec)

    MariaDB [(none)]> SET GLOBAL rpl_semi_sync_master_enabled = 1;
    Query OK, 0 rows affected (0.00 sec)

    MariaDB [(none)]> SET GLOBAL rpl_semi_sync_master_timeout = 2000;   #設置超時時間為2S
    Query OK, 0 rows affected (0.00 sec)

    配置slave

    MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
    Query OK, 0 rows affected (0.00 sec)

    MariaDB [(none)]> SET GLOBAL rpl_semi_sync_slave_enabled=1;
    Query OK, 0 rows affected (0.00 sec)

    驗證

    因為在我的環境中,即使是半同步復制,也是直接就完成,看不出效果,所以我們故意將slave節點關閉
    [root@node2 ~]# service mysql stop



    ##master創建數據庫
    MariaDB [(none)]> CREATE DATABASE TEST3;
    Query OK, 1 row affected (2.00 sec)        #等待2s, 超時不再等待,直接創建

    MariaDB [(none)]> CREATE DATABASE TEST4;
    Query OK, 1 row affected (0.00 sec)


    ##完成,這個可能不是特別直觀,但是由于我這邊環境實在做不出效果,望大家理解

    實驗中的思考

    • 如果主從服務器數據相差較大, 最好先使用主服務器的二進制日志在從服務器上replay一篇, 然后再進行同步

    總結

    這篇其實還打算寫SSL復制的,但是因為時間比較緊,就沒有寫了,總體來說不是特別的滿意,有很多地方沒有說明白,還望大家諒解。

    作者水平很低, 如果有錯誤及時指出, 如果你覺得本文寫的好請點一波贊~(≧▽≦)/~ 
    作者: AnyISaIln QQ: 1449472454 
    感謝: MageEdu

    原創文章,作者:Net18-AnyISalIn,如若轉載,請注明出處:http://www.www58058.com/15679

    (0)
    Net18-AnyISalInNet18-AnyISalIn
    上一篇 2016-04-28
    下一篇 2016-04-28

    相關推薦

    • Linux 基礎(7)——文本處理工具

      cat  tac  rev  more  less           head  tail cut  paste  wc               &nbs…

      2017-07-29
    • Python函數式編程指南(四):生成器

      轉自 http://www.cnblogs.com/huxi/archive/2011/07/14/2106863.html 生成器是迭代器,同時也并不僅僅是迭代器,不過迭代器之外的用途實在是不多,所以我們可以大聲地說:生成器提供了非常方便的自定義迭代器的途徑。 這是函數式編程指南的最后一篇,似乎拖了一個星期才寫好,嗯…… 轉載請注明原作者和原文地…

      Linux干貨 2015-03-09
    • lvs

      Lvs 一、lvs集群的類型:4類工作模式 1.1、lvs-nat 特點:通過將請求報文中的目標地址和目標端口修改為挑選出的某RS的RIP和PORT實現轉發。 客戶端訪問lvs集群服務,此時報文的源地址為cip,目標地址為vip,通過lvs進行dnat轉發后端服務器主機,此時,報文的源地址為cip,目標地址為rip;后端主機響應時,報文源地址為rip,目標地…

      Linux干貨 2016-10-30
    • linux 中條件測試判斷

      文件條件測試判斷:   -e 文件存在   -a 文件存在   這個選項的效果與-e相同. 但是它已經被"棄用"了, 并且不鼓勵使用.   -f 表示這個文件是一個一般文件(并不是目錄或者設備 文件)   -s 文件大小不為零   -d 表示這是一個目錄   -b 表示…

      Linux干貨 2017-02-02
    • 管理SYSTEMd

      核心概念unit,systemctl管理系統服務,

      Linux干貨 2018-01-04
    • test2

      歡迎使用馬克飛象 作業幫 示例筆記本 馬克飛象 幫助 Markdown 馬克飛象是一款專為印象筆記(Evernote)打造的Markdown編輯器,通過精心的設計與技術實現,配合印象筆記強大的存儲和同步功能,帶來前所未有的書寫體驗。特點概述: 功能豐富 :支持高亮代碼塊、LaTeX 公式、流程圖,本地圖片以及…

      Linux干貨 2017-03-20
    欧美性久久久久