MySQL主從複製:半同步、異步

大綱node

  • 前言mysql

  • 如何對MySQL進行擴展?sql

  • MySQL Replication WorkFlow數據庫

  • MySQL主從複製模式服務器

  • 實戰演練架構

    • MySQL異步複製實現負載均衡

    • MySQL半同步複製實現異步

  • 實驗中的思考socket

  • 總結性能

前言

本篇咱們介紹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主服務器寫入一段數據,在主庫寫入Binlog日誌後便可成功返回客戶端OK,無需等待Binlog日誌傳送給從庫。在一段時間內MySQL主服務器會將寫入的數據發送給MySQL從服務器,在這段時間以內,從服務器的數據可能會和主服務不一致,一旦主庫宕機,有可能會丟失日誌。
    半同步複製: 指的是客戶端鏈接到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: 指的是多主模式, 這種模式中的多臺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

注意: server_id是表明這臺服務器的id,在全部master和slaver中必須是惟一的,默認是1,推薦使用該服務器IP的最後一個冒號後面的數字,便於區分和記憶。

配置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;
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-log.000005 |      523 |              |                  |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

注意: 咱們要記錄下Master的日誌File的名稱和pos的數值,在配置Slaver的時候須要用到。

這裏的語句: GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'rpuser'@'%' IDENTIFIED BY 'passwd';

咱們來逐步分析下:

GRANT 授予

REPLICATION SLAVE權限:
The REPLICATION SLAVE privilege should be granted to accounts that are used by slave servers to connect to the current server as their master. Without this privilege, the slave cannot request updates that have been made to databases on the master server. 
REPLICATION SLAVE是一個必須而基本的權限,它直接授予slave服務器以該帳戶鏈接master後能夠執行replicate操做的權利。

REPLICATION CLIENT權限:

The REPLICATION CLIENT  privilege enables the use of SHOW MASTER STATUS and SHOW SLAVE STATUS. 
REPLICATION CLIENT 使得用戶可使用SHOW MASTER STATUS和SHOW SLAVE STATUS命令,也就是說這個權限是用於授予帳戶監視Replication情況的權力。

通常來講,咱們會單獨在主服務器建立一個專門用於Replication的帳戶。這個帳戶必須具備REPLICATION SLAVE權限,除此以外沒有必要添加沒必要要的權限,保證該用戶的職責單一。

ON *.*: 權限加載到的對象上,*.*表示全部;

TO: 把權限賦予給誰;

'rpuser'@'%' INDENTIFIED BY 'passwd': 用戶名爲rpuser的用戶,且該用戶的服務器ip爲%,這裏用了通配符,就是不限ip,若是是@'192.168.1.%'則表示192.168.1.1到192.168.1.255之間的全部ip,用'passwd'做爲密碼進行校驗。

這樣作的好處:一方面使用同一帳戶對Replication進行監視管理會很方便,沒必要區分slave,master,另外一方面,repl帳戶在slave和master上的配置是同樣的,這樣若是咱們切換slave和master,帳戶不須要作任何改動。

配置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啓動
#########省略##################

注意這裏的幾項配置:

    -> MASTER_HOST='172.16.1.2',
    -> MASTER_USER='rpuser',
    -> MASTER_PASSWORD='passwd',

   -> MASTER_LOG_FILE='master-log.000005',
    -> MASTER_LOG_POS=523;

必須和MASTER上執行的命令配置相符。

 

配置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)

正常狀況下,這兩個PLUGIN在master和slave上都應該被標準安裝,誰知道哪天備庫會不會被切換成主庫呢。

安裝完PLUGIN後,咱們能夠根據拓撲結構來定義主庫和備庫的配置,主要包括如下幾個配置項;
1.rpl_semi_sync_master_enabled  
  —控制主庫上是否開啓semisync, 打開或關閉,馬上生效
2.rpl_semi_sync_slave_enabled     
  —控制備庫是否開啓semisync,
當主庫打開semisync時,則必須至少要有一個連接的備庫是打開semisync的,不然主庫線程每次都會去等待,直至超時;所以若是想關閉semisync必需要先關閉主庫配置,再關閉備庫配置
3.rpl_semi_sync_master_timeout    
  —控制主庫上客戶端的等待時間,當超過這麼長時間等待後,客戶端返回,同步複製退化成原生的異步複製
  單位爲毫秒,默認值爲10000,即10秒  
4.rpl_semi_sync_master_wait_no_slave
默認打開,表示當備庫起來後,並跟上主庫時,自動切換到同步模式,若是關閉,即便備庫起來並跟上了,也不會啓用半同步;
5.rpl_semi_sync_master_trace_level 以及 rpl_semi_sync_slave_trace_level
— 輸出監控信息的級別,詳細點擊見文檔,不一樣的級別,可能輸出更詳細的信息,用於DEBUG
運行狀態變量也比較豐富,不細說了,網上介紹的不少,官方文檔也很詳細

 

驗證

由於在個人環境中,即便是半同步複製,也是直接就完成,看不出效果,因此咱們故意將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

相關文章
相關標籤/搜索