Mysql分布式部署 - 主從復(fù)制

1,概述

MySQL數(shù)據(jù)庫自身提供的主從復(fù)制功能,可以方便地實(shí)現(xiàn)數(shù)據(jù)的多處自動備份,完成Mysql的分布式部署。多個(gè)數(shù)據(jù)備份,解決了以下幾個(gè)問題:

  • 數(shù)據(jù)的安全性,不易丟失。
  • 讀寫分離,提高數(shù)據(jù)庫的讀寫性能。
  • 數(shù)據(jù)庫的負(fù)載均衡,提高數(shù)據(jù)庫的高可用和容錯(cuò)性。

2,Mysql主從復(fù)制的基本原理和步驟

2.1,基本介紹

MySQL內(nèi)建的復(fù)制功能是構(gòu)建大型、高性能應(yīng)用程序的基礎(chǔ)。將MySQL的數(shù)億分布到到多個(gè)系統(tǒng)上去,這種分步的機(jī)制,是通過將MySQL的某一臺主機(jī)(Master)的數(shù)據(jù)復(fù)制到其它主機(jī)(Slave)上,并重新執(zhí)行一遍來實(shí)現(xiàn)的。復(fù)制過程中,一臺服務(wù)器充當(dāng)Master,而一個(gè)或多個(gè)其它服務(wù)器充當(dāng)Slave。

2.2,實(shí)現(xiàn)步驟

MySQL之間數(shù)據(jù)復(fù)制的基礎(chǔ)是二進(jìn)制日志文件(binary log file)。一臺MySQL數(shù)據(jù)庫一旦啟用二進(jìn)制日志后,其作為master,它的數(shù)據(jù)庫中所有操作都會以“事件”的方式記錄在二進(jìn)制日志中,其他數(shù)據(jù)庫作為slave通過一個(gè)【I/O線程】與主服務(wù)器保持通信,并監(jiān)控master的二進(jìn)制日志文件的變化,如果發(fā)現(xiàn)master二進(jìn)制日志文件發(fā)生變化,則會把變化復(fù)制到自己的中繼日志中,然后slave的一個(gè) 【SQL線程】會把相關(guān)的“事件”執(zhí)行到自己的數(shù)據(jù)庫中,以此實(shí)現(xiàn)從數(shù)據(jù)庫和主數(shù)據(jù)庫的一致性,也就實(shí)現(xiàn)了主從復(fù)制。

主從復(fù)制過程,可以簡化為三個(gè)步驟:

  • Master將改變記錄到二進(jìn)制日志中。
  • Slave將Master的二進(jìn)制日志拷貝到它的中繼日志(Relay_log)。
  • Slave重做中繼日志中的事件,將改變反映它自己的數(shù)據(jù)。
Mysql主從復(fù)制-實(shí)現(xiàn)原理.jpg
  • 注意:在主從復(fù)制架構(gòu)中,所有對參與主從復(fù)制的數(shù)據(jù)表的更新操作,必須在主服務(wù)器上進(jìn)行。

2.3,典型的應(yīng)用場景

在一主多從的數(shù)據(jù)庫體系中,多個(gè)從服務(wù)器采用異步的方式更新主數(shù)據(jù)庫的變化,業(yè)務(wù)服務(wù)器在執(zhí)行寫或者相關(guān)修改數(shù)據(jù)庫的操作是在主服務(wù)器上進(jìn)行的,讀操作則是在各從服務(wù)器上進(jìn)行。

Mysql主從復(fù)制-一主多從.jpg

2.4. MySQL支持的復(fù)制類型

  • 基于語句的復(fù)制
    在主服務(wù)器上執(zhí)行的SQL語句,在從服務(wù)器上執(zhí)行同樣的語句。否則,你必須要小心,以避免用戶對主服務(wù)器上的表進(jìn)行的更新與對服務(wù)器上的表所進(jìn)行的更新之間的沖突。
    配置:binlog_format = 'STATEMENT'

  • 基于行的復(fù)制
    把改變的內(nèi)容復(fù)制過去,而不是把命令在從服務(wù)器上執(zhí)行一遍,從 MySQL 5.0開始支持。
    配置:binlog_format = 'ROW'

  • 混合類型的復(fù)制
    默認(rèn)采用基于語句的復(fù)制,一旦發(fā)現(xiàn)基于語句的無法精確的復(fù)制時(shí),就會采用基于行的復(fù)制。
    配置:binlog_format = 'MIXED'

3,實(shí)現(xiàn)過程(采用Docker方式部署)

3.1,準(zhǔn)備工作

  • 查找mysql的docker鏡像
kevin@apple:~$ docker search mysql
NAME                                                   DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                                                  MySQL is a widely used, open-source relati...   5693      [OK]       
mariadb                                                MariaDB is a community-developed fork of M...   1767      [OK]       
mysql/mysql-server                                     Optimized MySQL Server Docker images. Crea...   391                  [OK]
percona                                                Percona Server is a fork of the MySQL rela...   317       [OK]       
zabbix/zabbix-server-mysql                             Zabbix Server with MySQL database support       80                   [OK]
hypriot/rpi-mysql                                      RPi-compatible Docker Image with Mysql          79                   
centurylink/mysql                                      Image containing mysql. Optimized to be li...   58                   [OK]
zabbix/zabbix-web-nginx-mysql                          Zabbix frontend based on Nginx web-server ...   42                   [OK]
tutum/mysql                                            Base docker image to run a MySQL database ...   31                   
1and1internet/ubuntu-16-nginx-php-phpmyadmin-mysql-5   ubuntu-16-nginx-php-phpmyadmin-mysql-5          25                   [OK]
mysql/mysql-cluster                                    Experimental MySQL Cluster Docker images. ...   19                   
centos/mysql-57-centos7                                MySQL 5.7 SQL database server                   18                   
schickling/mysql-backup-s3                             Backup MySQL to S3 (supports periodic back...   16                   [OK]
linuxserver/mysql                                      A Mysql container, brought to you by Linux...   14                   
zabbix/zabbix-proxy-mysql                              Zabbix proxy with MySQL database support        10                   [OK]
centos/mysql-56-centos7                                MySQL 5.6 SQL database server                   8                    
openshift/mysql-55-centos7                             DEPRECATED: A Centos7 based MySQL v5.5 ima...   6                    
circleci/mysql                                         MySQL is a widely used, open-source relati...   3                    
frodenas/mysql                                         A Docker Image for MySQL                        3                    [OK]
dsteinkopf/backup-all-mysql                            backup all DBs in a mysql server                3                    [OK]
inferlink/landmark-mysql                               landmark-mysql                                  0                    [OK]
ansibleplaybookbundle/mysql-apb                        An APB which deploys RHSCL MySQL                0                    [OK]
cloudposse/mysql                                       Improved `mysql` service with support for ...   0                    [OK]
cloudfoundry/cf-mysql-ci                               Image used in CI of cf-mysql-release            0                    
openzipkin/zipkin-mysql                                Mirror of https://quay.io/repository/openz...   0                    
  • 創(chuàng)建網(wǎng)絡(luò),docker有四種網(wǎng)絡(luò)類型(bridge、container、host和none),我們使用的是none,可以設(shè)置靜態(tài)IP
kevin@apple:~$ docker network create --subnet=172.18.0.0/24 my_network
0b85ab8c7809886bb7fada8c4a8970b5692f11dbd950790f1e9b1e098691f114
  • 啟動新容器master,命名為mysql_master,設(shè)置靜態(tài)IP為172.18.0.10
kevin@apple:~$ docker run -it --name mysql_master -h mysql_master \
-p 13306:3306 --net my_network --ip 172.18.0.10 \
--add-host mysql_master:172.18.0.10 \
mysql:latest /bin/bash
  • 啟動新容器slave,命名為mysql_slave,設(shè)置靜態(tài)IP為172.18.0.11
kevin@apple:~$ docker run -it --name mysql_slave -h mysql_slave \
-p 13307:3306 --net my_network --ip 172.18.0.11 \
--add-host mysql_master:172.18.0.10 \
mysql:latest /bin/bash
  • 在docker容器中,部署相關(guān)軟件
root@mysql_master:~$ apt-get update
root@mysql_master:~$ apt-get install vim
# 安裝ifconfig、netstat
root@mysql_master:~$ apt-get install net-tools

3.2,主服務(wù)器

  • 開啟二進(jìn)制日志,并配置唯一的server-id
# 在[mysqld]下增加配置
root@mysql_master:/etc/mysql/mysql.conf.d# vi /etc/mysql/mysql.conf.d/mysqld.cnf 
...
...
# 開啟二進(jìn)制日志,可以寫絕對路徑,例如/var/log/mysql/master-bin
log-bin   = mysql-bin
# Mysql服務(wù)ID,必須保證唯一
server-id = 1

# 不進(jìn)行主從復(fù)制的db
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
# 進(jìn)行主從復(fù)制的db
binlog-do-db = test

# 只保存最近7天的bin-log文件,避免文件過多
expire_logs_days=7
  • 重啟Mysql服務(wù)
root@mysql_master:/etc/mysql/mysql.conf.d# service mysql restart
  • 創(chuàng)建一個(gè)用于slave和master通信的用戶賬號slave1
mysql> CREATE USER 'slave1'@'%' IDENTIFIED BY '123456';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave1'@'%';
  • 創(chuàng)建測試賬號和數(shù)據(jù)庫
mysql> Grant all privileges on *.* to 'test'@'%' identified by '123456' with grant option;
mysql> Create database test;
  • 查看master狀態(tài),獲得master二進(jìn)制日志文件名及位置
mysql> show master status;
+------------------+----------+--------------+--------------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB         | Executed_Gtid_Set |
+------------------+----------+--------------+--------------------------+-------------------+
| mysql-bin.000005 |      955 | test         | mysql,information_schema |                   |
+------------------+----------+--------------+--------------------------+-------------------+
1 row in set (0.00 sec)

3.3,從服務(wù)器

  • 配置唯一的server-id
# 在[mysqld]下增加配置
root@mysql_slave:/etc/mysql/mysql.conf.d# vi /etc/mysql/mysql.conf.d/mysqld.cnf 
...
...
# Mysql服務(wù)ID,必須保證唯一
server-id = 2
  • 使用master分配的用戶賬號讀取master二進(jìn)制日志
mysql> CHANGE MASTER TO
MASTER_HOST='mysql_master',
MASTER_USER='slave1',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000005',
MASTER_LOG_POS=955;
  • 啟用slave服務(wù),并查看狀態(tài)
mysql> start slave;
mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: mysql_master
                  Master_User: slave1
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000005
          Read_Master_Log_Pos: 1424
               Relay_Log_File: mysql_slave-relay-bin.000004
                Relay_Log_Pos: 1637
        Relay_Master_Log_File: mysql-bin.000005
             Slave_IO_Running: Yes                                     # IO線程是啟動狀態(tài),如果是No,可以查看下面日志,分析處理
            Slave_SQL_Running: Yes                                     # SQL線程是啟動狀態(tài),如果是No,可以查看下面日志,分析處理
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 1424
              Relay_Log_Space: 2016
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
                  Master_UUID: 0f5421ba-0ede-11e8-b442-0242ac12000a
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)

4,測試

4.1,測試用例1

  • 在master中,創(chuàng)建數(shù)據(jù)表,增加2行數(shù)據(jù),觀察slave數(shù)據(jù)變化是否一致(結(jié)果一致)
mysql> CREATE TABLE test.`student` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

mysql> Insert into test.student(name) values('aaa');
mysql> Insert into test.student(name) values('bbb');

mysql> Select * from test.student;

4.2,測試用例2

  • 在master中,刪除1行數(shù)據(jù),更新1行數(shù)據(jù),觀察slave的數(shù)據(jù)變化(結(jié)果一致)
mysql> delete from test.student where id = 1;
mysql> update test.student set name = 'ccc' where id = 2;

4.3,測試用例3

  • 在master中,刪除1個(gè)數(shù)據(jù)表,觀察slave的數(shù)據(jù)變化(結(jié)果一致)
mysql> drop table student;

4.4,測試用例4

  • 在master中,刪除數(shù)據(jù)庫test,或創(chuàng)建數(shù)據(jù)庫test,觀察slave的數(shù)據(jù)變化(結(jié)果一致)
mysql> drop database test;
mysql> create database test;

5,高級應(yīng)用

5.1,數(shù)據(jù)庫復(fù)制

如果是新部署的MySQL主從服務(wù)器,這一步不需要。
如果Master之前有數(shù)據(jù),需要把Master的數(shù)據(jù)導(dǎo)出并還原到Slave上,要保證Master和Slave服務(wù)器中的數(shù)據(jù)是一樣的。
建議導(dǎo)出Master庫的時(shí)候進(jìn)行鎖表,導(dǎo)完后再解鎖。

  • 鎖表,并查看master的bin-log日志文件名稱和位置
mysql> flush tables with read lock;
mysql> show master status;
  • 全量導(dǎo)出Master數(shù)據(jù)庫
root@mysql_master:/home# mysqldump -utest -p123456 test > test.sql
  • 手動導(dǎo)入到Slave
root@mysql_slave:/home# mysql -utest -p123456 -e 'create database test;'
root@mysql_slave:/home# mysql -utest -p123456 -e 'show databases;'
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |
+--------------------+
root@mysql_slave:/home# mysql -utest -p123456 test < test.sql
  • 解鎖master數(shù)據(jù)庫
mysql> unlock tables;

5.2,MySQL主從一致性檢查

  • 寫一個(gè)監(jiān)控腳本,用來監(jiān)控Slave中的兩個(gè)"yes",如果只有一個(gè)"yes"或者零個(gè),就表明主從有問題。
  • 通過Percona-Toolkit這個(gè)工具來實(shí)現(xiàn)的,Percona Toolkit是一組高級的命令行工具,用來管理MySQL和系統(tǒng)任務(wù)。

6,參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。