MySQL集羣搭建(1)-主備搭建

數據庫在任何業務中都是最重要的環節之一,這就對數據庫架構提出的較高的要求。單點數據庫永遠不該該出如今生產環境,咱們已經目擊過太多因爲單點、備份缺失形成的損失,因此,搭建高可用 MySQL 集羣是很是有必要的。mysql

搭建集羣有如下幾點好處:sql

  1. 高可用性,在主節失效時自動切換,不須要技術人員緊急處理
  2. 高吞吐,能夠多個節點同時提供讀取數據服務,下降主節點負載,實現高吞吐
  3. 可擴展性強,支持在線擴容
  4. 無影響備份,在備節點進行備份操做不會對業務產生影響

要說缺點,有如下幾點:數據庫

  1. 架構複雜,在部署、管理方面對技術人員有要求
  2. 備節點拉取主節點日誌時會對主節點服務器性能有必定影響
  3. 若是配置了半同步複製,會對事務提交有一點影響

總的說,集羣是必定要搭建的,誰敢把本身的數據跑在一個隨時會有風險的數據庫上呢。接下來我會以幾篇文章介紹怎麼從簡單地主備模式到高可用架構。本節主要介紹如何搭建 MySQL 主備,注重操做,不會有太多理論講解。segmentfault

1 環境準備

1.1 啓動數據庫

在兩臺機器分別啓動 MySQL 實例, MySQL 搭建方式能夠參考 MySQL 安裝(二進制版)服務器

IP 系統 端口 MySQL版本 節點
192.168.41.83 Centos6.8 3306 5.7.20 Master
192.168.41.72 Centos6.8 3306 5.7.20 Salve

關鍵配置:架構

Master:socket

[client]
port = 3306
default-character-set=utf8mb4
socket = /data/mysql_db/mysql_seg_3306/mysql.sock

[mysqld]
datadir = /data/mysql_db/mysql_seg_3306
basedir = /usr/local/mysql57
tmpdir = /tmp
socket = /data/mysql_db/mysql_seg_3306/mysql.sock
pid-file = /data/mysql_db/mysql_seg_3306/mysql.pid
skip-external-locking = 1
skip-name-resolve = 1
port = 3306
server_id = 833306

default-storage-engine = InnoDB
character-set-server = utf8mb4
default_password_lifetime=0

#### log ####
log_timestamps=system
log_bin = /data/mysql_log/mysql_seg_3306/mysql-bin
log_bin_index = /data/mysql_log/mysql_seg_3306/mysql-bin.index
binlog_format = row
relay_log_recovery=ON
relay_log=/data/mysql_log/mysql_seg_3306/mysql-relay-bin
relay_log_index=/data/mysql_log/mysql_seg_3306/mysql-relay-bin.index
log_error = /data/mysql_log/mysql_seg_3306/mysql-error.log

#### replication ####
replicate_wild_ignore_table = information_schema.%,performance_schema.%,sys.%

#### semi sync replication settings #####
plugin_dir=/usr/local/mysql57/lib/plugin
plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
loose_rpl_semi_sync_master_timeout = 5000

Salve函數

[client]
port = 3306
default-character-set=utf8mb4
socket = /data/mysql_db/mysql_seg_3306/mysql.sock

[mysqld]
datadir = /data/mysql_db/mysql_seg_3306
basedir = /usr/local/mysql57
tmpdir = /tmp
socket = /data/mysql_db/mysql_seg_3306/mysql.sock
pid-file = /data/mysql_db/mysql_seg_3306/mysql.pid
skip-external-locking = 1
skip-name-resolve = 1
port = 3306
server_id = 723306
read_only=1

default-storage-engine = InnoDB
character-set-server = utf8mb4
default_password_lifetime=0

#### log ####
log_timestamps=system
log_bin = /data/mysql_log/mysql_seg_3306/mysql-bin
log_bin_index = /data/mysql_log/mysql_seg_3306/mysql-bin.index
binlog_format = row
relay_log_recovery=ON
relay_log=/data/mysql_log/mysql_seg_3306/mysql-relay-bin
relay_log_index=/data/mysql_log/mysql_seg_3306/mysql-relay-bin.index
log_error = /data/mysql_log/mysql_seg_3306/mysql-error.log

#### replication ####
replicate_wild_ignore_table = information_schema.%,performance_schema.%,sys.%

#### semi sync replication settings #####
plugin_dir=/usr/local/mysql57/lib/plugin
plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
loose_rpl_semi_sync_master_timeout = 5000

配置解析性能

  • datadir, basedir, tmpdir 分別爲數據文件位置、數據庫程序安裝位置、臨時文件位置
  • server_id 實例id,注意,同一集羣機器的 server_id 不能相同
  • read_only 是否只讀, 通常在備庫設置
  • log_bin, log_bin_index 二進制日誌位置、二進制日誌索引文件位置
  • binlog_format 二進制日誌格式,row 表示記錄每條數據變化狀況、statement 表示記錄相關 sql 語句、mixed 表示兩種混用,在搭建集羣的時候建議使用 row 格式,若是是用 sql 語句來同步數據很容易出現數據不一致的狀況
  • relay_log_recovery slave 宕機後,假如中繼日誌損壞,則從新拉取日誌,爲了保證中繼日誌完整性,建議開啓
  • relay_log, relay_log_index 中繼日誌以及中繼日誌索引文件位置
  • log_error 錯誤日誌位置
  • replicate_wild_ignore_table 同步時須要忽略的表,這裏咱們忽略了系通通計表,若是出現奇怪的同步失敗狀況,能夠嘗試開啓
  • plugin_dir 插件位置
  • plugin_load 啓動時須要加載的插件
  • loose_rpl_semi_sync_master_enabled 是否開啓無損半同步複製-主庫(建議主備都開啓,方便主備切換)
  • loose_rpl_semi_sync_slave_enabled 是否開啓無損半同步複製-備庫(建議主備都開啓,方便主備切換)

1.2 插入數據

咱們假設 Master 是正在使用的數據庫,如今要在線搭建備庫,咱們往 Master 節點插入一些測試數據測試

[mysql@mysql-test-83 ~]$ mydb-test_seg
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 29
Server version: 5.7.21-log MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

db83-3306>>show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

db83-3306>>create database mytest;
Query OK, 1 row affected (0.00 sec)

db83-3306>>use mytest;
Database changed
db83-3306>>create table test1(
    -> id int not null primary key auto_increment,
    -> name varchar(16) not null default '',
    -> age int not null default 0
    -> ) engine = InnoDb charset = utf8;
Query OK, 0 rows affected (0.01 sec)
db83-3306>>insert into test1 values (0, 'a', 16), (0, 'b', 17), (0, 'c', 18), (0, 'd', 19);
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

db83-3306>>select * from test1;
+----+------+-----+
| id | name | age |
+----+------+-----+
|  1 | a    |  16 |
|  2 | b    |  17 |
|  3 | c    |  18 |
|  4 | d    |  19 |
+----+------+-----+
4 rows in set (0.00 sec)

2 在線搭建主從

如今咱們的環境以下

  • 192.168.41.83:3306 Master 節點,正在使用
  • 192.168.41.72:3306 新搭建數據庫,要在上面作 192.168.41.83 的備庫

2.1 建立同步用戶

咱們建立一個用戶名爲 repl 的用戶,授予 REPLICATION SLAVE 權限專門用來同步

db83-3306>>CREATE USER 'repl'@'%' IDENTIFIED BY 'repl';
Query OK, 0 rows affected (5.01 sec)

db83-3306>>GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
Query OK, 0 rows affected (0.00 sec)

db83-3306>>flush privileges;
Query OK, 0 rows affected (0.00 sec)

2.2 備份數據

經常使用的備份數據的方式有 innobackupexmysqldump,這裏數據量少,咱們用 mysqldump 進行全備

[mysql@mysql-test-83 ~]$ /usr/local/mysql57/bin/mysqldump -S /data/mysql_db/mysql_seg_3306/mysql.sock -F --opt -R --single-transaction --master-data=2 --default-character-set=utf8 -A > mysql_backup_full.sql

參數解析:

  • -S 選擇 socket 文件,本機鏈接數據庫能夠用這種方法,也能夠指定 ip、端口進行鏈接
  • -F 開始導出以前刷新日誌
  • --opt 若是有這個參數表示同時激活了 mysqldump 命令的 quick,add-drop-table,add-locks,extended-insert,lock-tables 參數

    • --quick 表明忽略緩衝輸出,mysqldump 命令直接將數據導出到指定的SQL文件
    • --add-drop-table 就是在每一個 CREATE TABEL 命令以前增長 DROP-TABLE IF EXISTS 語句,防止數據表重名
    • --add-locks 在INSERT數據以前和以後鎖定和解鎖對應的數據表
    • --extended-insert 表示能夠多行插入
  • -R 導出存儲過程以及自定義函數, 若是有用到存儲過程, 須要加這個參數
  • --single-transaction (innodb)設置事務的隔離級別爲可重複讀,即 REPEATABLE READ,這樣能保證在一個事務中全部相同的查詢讀取到一樣的數據, 若是所有表都爲 InnoDB 就帶上這個參數,保證數據一致性,備份時不會鎖表。若是有 MyISAM 的表,須要鎖表備份才能保證數據的一致性
  • --lock-all-tables 備份過程加讀鎖, single-transaction 選項和 lock-all-tables 選項是二選一的
  • --master-data=2 記錄當前二進制日誌位置, master_data取1和取2的區別,只是後者把 change master ... 命令註釋起來了
  • --default-character-set 選擇編碼, 這個選項很是重要, 編碼選不對或者沒有設置很容易形成亂碼
  • -A 表明備份全部的庫

數據備份完畢後,把數據文件直接傳輸到 Slave 機器上

[mysql@mysql-test-83 ~]$ ll
total 772
-rw-rw-r-- 1 mysql mysql 786921 Nov 17 10:38 mysql_backup_full.sql
[mysql@mysql-test-83 ~]$ rsync -avzP mysql_backup_full.sql 192.168.41.72:/home/mysql/

2.3 數據恢復

在 Slave 機器上直接執行 sql 文件導入數據

[mysql@mysql-test-72 ~]$ ll mysql_backup_full.sql 
-rw-rw-r-- 1 mysql mysql 786921 Nov 17 10:38 mysql_backup_full.sql
[mysql@mysql-test-72 ~]$ /usr/local/mysql57/bin/mysql -S /data/mysql_db/mysql_seg_3306/mysql.sock < mysql_backup_full.sql

導入完畢,咱們能夠看到數據和 Master 的備份數據一致

db72-3306>>show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| mytest             |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

db72-3306>>use mytest;
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
db72-3306>>show tables;
+------------------+
| Tables_in_mytest |
+------------------+
| test1            |
+------------------+
1 row in set (0.00 sec)

db72-3306>>select * from test1;
+----+------+-----+
| id | name | age |
+----+------+-----+
|  1 | a    |  16 |
|  2 | b    |  17 |
|  3 | c    |  18 |
|  4 | d    |  19 |
+----+------+-----+
4 rows in set (0.00 sec)

2.4 開啓同步

回到備份文件,咱們從頭部找到 Master 備份時間點的二進制日誌位置

[mysql@mysql-test-72 ~]$ head -30 mysql_backup_full.sql | grep 'CHANGE MASTER TO MASTER_LOG_FILE'
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=154;

MASTER_LOG_FILEMASTER_LOG_POS 就是在 Master 執行 show master status 獲得的二進制位置信息。如今,咱們執行同步命令

-- 重置複製
-- reset slave;

-- 同步配置
CHANGE MASTER TO
MASTER_HOST='192.168.41.83',
MASTER_PORT=3306,
MASTER_USER='repl',
MASTER_PASSWORD='repl',
MASTER_LOG_FILE='mysql-bin.000004',
MASTER_LOG_POS=154;

-- 開啓同步
start slave

實際執行結果以下

db72-3306>>CHANGE MASTER TO
    -> MASTER_HOST='192.168.41.83',
    -> MASTER_PORT=3306,
    -> MASTER_USER='repl',
    -> MASTER_PASSWORD='repl',
    -> MASTER_LOG_FILE='mysql-bin.000004',
    -> MASTER_LOG_POS=154;
Query OK, 0 rows affected, 2 warnings (0.20 sec)

db72-3306>>start slave;
Query OK, 0 rows affected (0.01 sec)

查看同步狀態

db72-3306>>show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.41.83
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000004
          Read_Master_Log_Pos: 154
               Relay_Log_File: mysql-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: mysql-bin.000004
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              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: 154
              Relay_Log_Space: 527
              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: 833306
                  Master_UUID: 15958368-e9a0-11e8-a98c-ecb1d77febe4
             Master_Info_File: /data/mysql_db/mysql_seg_3306/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)

ERROR: 
No query specified

咱們能夠從 Slave_IO_Running, Slave_SQL_Running, Seconds_Behind_Master 這三個參數能夠判斷出同步狀態是否正常

  • Slave_IO_Running 取 Master 日誌的線程, Yes 爲正在運行
  • Slave_SQL_Running 從日誌恢復數據的線程, Yes 爲正在運行
  • Seconds_Behind_Master 當前數據庫相對於主庫的數據延遲, 這個值是根據二進制日誌的時間戳計算獲得的(秒)

從輸出結果能夠看到咱們的同步是正常的,下面咱們來測試一下

2.5 同步測試

在 Master 節點插入新數據

db83-3306>>insert into test1 values(0, 'chengqm', 24);
Query OK, 1 row affected (0.00 sec)

db83-3306>>select * from test1;
+----+---------+-----+
| id | name    | age |
+----+---------+-----+
|  1 | a       |  16 |
|  2 | b       |  17 |
|  3 | c       |  18 |
|  4 | d       |  19 |
|  5 | chengqm |  24 |
+----+---------+-----+
5 rows in set (0.00 sec)

備節點檢查數據同步狀態

db72-3306>>select * from test1;
+----+---------+-----+
| id | name    | age |
+----+---------+-----+
|  1 | a       |  16 |
|  2 | b       |  17 |
|  3 | c       |  18 |
|  4 | d       |  19 |
|  5 | chengqm |  24 |
+----+---------+-----+
5 rows in set (0.00 sec)

能夠看到數據已經同步到備節點,本次主備搭建完成

相關文章
相關標籤/搜索