mysql高可用方案


第一節:mysql 高可用方案

1.1 一主一從架構

  mysql 配置為主從模式,從庫是主庫的 backup,同一時間設置其中一台為主服務器,提供讀寫,另一台服務器作為熱備,不提供讀寫,通過復制與主服務器數據保持一致,二者均開啟 binlog。

(1)主從復制實現

  在主庫把數據更改記錄到 binlog 中;

  備庫將主庫的日志復制到自己的 relaylog 中;

  備庫讀取 relaylog 中的事件,將其重放到備庫上。

(2)主從復制關鍵技術

    異步復制、半同步復制

 

 1.2 雙主(主從)架構

  在一主一從架構的基礎上配置雙向復制和 Keepalived 自動切換功能,通過周期性調用監測腳本,監測進程,實現故障時 VIP 的無縫切換,當活躍點出現故障時,通過 VIP+Keepalived 腳本執行實現向另一台數據庫的切換,以此實現 mysql 架構的高可用。

(1)Keepalived 切換實現

    雙向復制運行;

    VIP 所在的庫作為主庫;

    主庫出現問題時,VIP 切換至另一個主庫。

(2)Keepalived 切換關鍵技術

    VRRP 原理、Keepalived 監測機制


1.3 MHA + 一主兩從架構

  MHA(Master High Availability)在 mysql 高可用方面是一個相對成熟的解決方案。在 mysql 故障切換的過程中,MHA 能做到在 0-30 秒之內自動完成數據庫的故障切換工作,並且在進行故障切換的過程中,MHA 能在最大程度上保證數據的一致性,已達到真正意義上的高可用,但 GTID 出現后 MHA 功能弱化。

(1)MHA切換實現

    主庫;備主;備庫;

    MHA 配合 VIP 漂移;

    補齊數據。

(2)MHA切換關鍵技術

    MHA manager、GTID(全局事務標志)出現,MHA弱化

      一個事務對應一個唯一ID,一個GTID在一個服務器上只會執行一次(一個事務在從庫上只能出現一次)

1.4 mysql 集群架構

  集群架構原理(PXC):節點接收 sql 請求后,對於 ddl 操作,在 commit 之前,由 wsrep API 調用 galera 庫進行集群內廣播,所有其他節點驗證成功后事務在集群所有節點進行提交,反之 roll back。PXC 保證整個集群所有數據的強一致性,滿足:Consistency和Availability。

(1)mysql 集群實現

    上層中間調度如 HAproxy;

    調度到的 Node上進行讀寫;

    同步至其他兩個節點。

(2)mysql 集群關鍵技術

    同步復制、wsrep 插件技術

2、mysql 主從復制

2.1 mysql 主從復制概念

  mysql 主從復制是指數據可以從一個 mysql 數據庫服務器主節點復制到一個或多個從節點。mysql 默認采用異步復制方式,這樣從節點不用一直訪問主服務器來更新自己的數據,數據的更新可以在遠程連接上進行,從節點可以復制主數據庫中的所有數據庫或者特定的數據庫,或者特定的表。

2.2 mysql 主從復制的主要用途

(1)讀寫分離

(2)數據實時備份,當系統某節點發生故障時,可以進行故障切換

(3)高可用性(HA)

  隨着系統中業務訪問量的增大,如果是單機部署數據庫,就會導致 I/O 訪問頻率過高。有了主從復制,增加多個數據存儲節點,將負載分布在多個從節點上,降低單機磁盤 I/O 訪問的頻率,提高單個機器的 I/O 性能。

2.3 mysql 主從復制原理

  過程:主庫開啟 binlog 功能並授權從庫連接主庫,主庫 IO 線程根據從庫的請求,從 master.info 開始記錄的位置點向下開始取信息,同時把取到的位置點和最新的位置與 binlog 信息一同發給從庫 IO 線程,從庫將相關的 sql 語句存放在 relay-log 里面,最終從庫的 sql 線程將 relay-log 里的 sql 語句應用到從庫上,至此整個同步過程完成,之后將是無限重復上述過程。

  binlog 輸出線程:每當有從庫連接到主庫的時候,主庫都會創建一個線程然后發送 binlog 內容到從庫。對於每一個即將發送給從庫的 sql 事件,binlog 輸出線程會將其鎖住。一旦該事件被線程讀取完之后,該鎖會被釋放,即使在該事件完全發送到從庫的時候,該鎖也會被釋放。在從庫里,當復制開始的時候,從庫就會創建兩個線程進行處理:

  從庫 I/O 線程:當 START SLAVE 語句在從庫開始執行之后,從庫創建一個 I/O 線程,該線程連接到主庫並請求主庫發送 binlog 里面的更新記錄到從庫上。從庫 I/O 線程讀取主庫的 binlog 輸出線程發送的更新並拷貝這些更新到本地文件,其中包括 relay log 文件。

  從庫的 SQL 線程:從庫創建一個 SQL 線程,這個線程讀取從庫 I/O 線程寫到 relay log 的更新事件並執行。

  可以知道,對於每一個主從復制的連接,都有三個線程。擁有多個從庫的主庫為每一個連接到主庫的從庫創建一個 binlog 輸出線程,每一個從庫都有它自己的 I/O 線程和 SQL 線程。

  從庫通過創建兩個獨立的線程,使得在進行復制時,從庫的讀和寫進行了分離。因此,即使負責執行的線程運行較慢,負責讀取更新語句的線程並不會因此變得緩慢。比如說,如果從庫有一段時間沒運行了,當它在此啟動的時候,盡管它的 SQL 線程執行比較慢,它的 I/O 線程可以快速地從主庫里讀取所有的 binlog 內容。這樣一來,即使從庫在 SQL 線程執行完所有讀取到的語句前停止運行了,I/O 線程也至少完全讀取了所有的內容,並將其安全地備份在從庫本地的 relay log,隨時准備在從庫下一次啟動的時候執行語句。

2.4 主從復制的實現

(1)環境構建:基於 centos7 操作系統,mariadb 數據庫(同 mysql 數據庫)

master節點:192.168.129.128
slave1節點:192.168.129.129

(2)分別在 master 節點和 slave1 節點上關閉防火牆,關閉 selinux

#master節點:
[root@Master ~]#systemctl stop firewalld
[root@Master ~]#systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@Master ~]# sed -ri '/^SELINUX=/s/(SELINUX=).*/\1disabled/' /etc/selinux/config#slave1節點:
[root@Slave1 ~]# systemctl stop firewalld
[root@Slave1 ~]# systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@Slave1 ~]# sed -ri '/^SELINUX=/s/(SELINUX=).*/\1disabled/' /etc/selinux/config

(3)master 節點和 slave1 節點上分別安裝 mariadb:

#兩個節點分別執行:
yum install mariadb-server -y

(4)在主服務器(master)上:

  啟用二進制日志

  選擇一個唯一的server-id

  創建具有復制權限的用戶

[root@Master ~]#vim /etc/my.cnf    
[mysqld]
log-bin=master-bin
# 行模式
binlog_format = row
# 刷新binlog到磁盤
sync_binlog = 1
# 禁止域名解析
skip_name_resolv = 1
# 同步設置的重要參數
log_slave_updates = 1
# 設置唯一id
server_id = 128
datadir=/var/lib/mysql
[root@Master ~]#systemctl restart mariadb
[root@Master ~]#mysql
MariaDB [(none)]> reset master;    #刪除所有的binglog日志文件,並將日志索引文件清空,重新開始所有新的日志文件。用於第一次進行搭建主從庫時,進行主庫binlog初始化工作;

Query OK, 0 rows affected (0.02 sec)

MariaDB [(none)]> grant replication slave,replication client on *.*
    -> to rep@'192.168.129.%' identified by 'localhost';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

(5)在從服務器(slave1)上

  啟用中繼日志(二進制日志可開啟,也可不開啟)

  選擇一個唯一的 server-id

  連接至主服務器,並開始復制

  首先測試是否能遠程登錄 master 節點上的數據庫:

[root@Slave1 ~]# mysql -h 192.168.129.128 -urep -plocalhost
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 5.5.56-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

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

MariaDB [(none)]> quit    #測試成功,退出

  配置從服務器:

[root@Slave1 ~]# vim /etc/my.cnf
[mysqld]
log-bin=slave1-bin
binlog_format = row
sync_binlog = 1
skip_name_resolv = 1
log_slave_updates = 1
server_id = 129
datadir=/var/lib/mysql
[root@Slave1 ~]# systemctl start mariadb
[root@Slave1 ~]# mysql
MariaDB [(none)]> reset master;
Query OK, 0 rows affected (0.02 sec)

MariaDB [(none)]> change master to
    -> master_host='192.168.129.128',
    -> master_user='rep',
    -> master_password='localhost',
    -> master_log_file='master-bin.000001',
    -> master_log_pos=0;
Query OK, 0 rows affected (0.04 sec)

MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: 
                  Master_Host: 192.168.129.128
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000001
          Read_Master_Log_Pos: 4
               Relay_Log_File: mariadb-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: master-bin.000001
             Slave_IO_Running: No
            Slave_SQL_Running: No

MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.01 sec)

MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.129.128
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000001
          Read_Master_Log_Pos: 493
               Relay_Log_File: mariadb-relay-bin.000002
                Relay_Log_Pos: 778
        Relay_Master_Log_File: master-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

(6)測試:master 創建數據庫數據,slave 節點查看是同步了 master 節點的數據庫信息

  master節點:

MariaDB [(none)]> show processlist\G
*************************** 2. row ***************************
      Id: 5
    User: rep
    Host: 192.168.129.129:47964
      db: NULL
 Command: Binlog Dump
    Time: 40
   State: Master has sent all binlog to slave; waiting for binlog to be updated
    Info: NULL
Progress: 0.000
2 rows in set (0.00 sec)

MariaDB [(none)]> create database bbs;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> create table bbs.t1(id int);
Query OK, 0 rows affected (0.02 sec)

MariaDB [(none)]> insert into bbs.t1 values(1);
Query OK, 1 row affected (0.01 sec)

MariaDB [(none)]> select * from bbs.t1;
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

  slave1節點:

MariaDB [(none)]> show processlist\G
*************************** 1. row ***************************
      Id: 2
    User: root
    Host: localhost
      db: NULL
 Command: Query
    Time: 0
   State: NULL
    Info: show processlist
Progress: 0.000
*************************** 2. row ***************************
      Id: 3
    User: system user
    Host: 
      db: NULL
 Command: Connect
    Time: 203
   State: Waiting for master to send event
    Info: NULL
Progress: 0.000
*************************** 3. row ***************************
      Id: 4
    User: system user
    Host: 
      db: NULL
 Command: Connect
    Time: 42
   State: Slave has read all relay log; waiting for the slave I/O thread to update it
    Info: NULL
Progress: 0.000
3 rows in set (0.00 sec)

MariaDB [(none)]> select * from bbs.t1;    #查看數據主從配置成功
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.01 sec)

2.5 mysql 主從狀況監測主要參數

  Slave_IO_Running:線程是否打開 YES/No/NULL

  Slave_SQL_Running:線程是否打開 YES/No/NULL

  Seconds_Behind_Master:和主庫比同步的延遲的秒數

2.6 可能導致主從延時的因素

  主從時鍾是否一致

  網絡通信是否存在延遲

  是否和日志類型,數據過大有關

  從庫性能,有沒開啟 binlog

  從庫查詢是否優化

3、mysql 雙主架構

3.1 實現

(1)兩台 mysql 都可讀寫,互為主備,默認只使用一台(masterA)負責數據的寫入,另一台(masterB)備用;

(2)masterA 是 masterB 的主庫,masterB 又是 masterA 的主庫,它們互為主從;

(3)兩台主庫之間做高可用,可以采用 keepalived 等方案(使用 VIP 對外提供服務);

(4)所有提供服務的從服務器與 masterB 進行主從同步(雙主多從);

(5)建議采用高可用策略的時候,masterA 或 masterB 均不因宕機恢復后而搶占 VIP(非搶占模式);

  這樣做可以在一定程度上保證主庫的高可用,在一台主庫 down 掉之后,可以在極短的時間內切換到另一台主庫上(盡可能減少主庫宕機對業務造成的影響),減少了主從同步給線上主庫帶來的壓力;

  masterB 可能會一直處於空閑狀態(可以用它當從庫,負責部分查詢);

  主庫后面提供服務的從庫要等 masterB 先同步完了數據后才能去 masterB 上去同步數據,這樣可能會造成一定程度的同步延時;

 3.2 mysql 主主同步配置

   主主環境構建:同樣基於centos7-mariadb

    mysql1:192.168.129.128

    mysql2:192.168.129.129

(1)關閉防火牆、selinux(同上:主從)

(2)mysql1 節點:

[root@mysql1 ~]#vim /etc/my.cnf
log-bin=mysql-bin
server-id = 4
[root@mysql1 ~]#systemctl start mariadb
[root@mysql1 ~]#mysql
MariaDB [(none)]> reset master;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> grant replication slave,replication client on *.*
    -> to rep@'192.168.129.%' identified by 'localhost';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> change master to
    -> master_host='192.168.129.129',
    -> master_user='rep',
    -> master_password='localhost',
    -> master_log_file='mysql-bin.000001',
    -> master_log_pos=0;
Query OK, 0 rows affected (0.02 sec)

MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: 
                  Master_Host: 192.168.129.129
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 4
               Relay_Log_File: mariadb-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: No
            Slave_SQL_Running: No
  
MariaDB [(none)]> slave start;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Connecting to master
                  Master_Host: 192.168.129.129
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 4
               Relay_Log_File: mariadb-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Connecting
            Slave_SQL_Running: Yes

(3)mysql2 節點:

[root@mysql2 ~]# vim /etc/my.cnf
log-bin=mysql-bin
server-id = 251
[root@mysql2 ~]# systemctl start mariadb
[root@mysql2 ~]# mysql

MariaDB [(none)]> reset master;
Query OK, 0 rows affected (0.01 sec)

MariaDB [(none)]> grant replication slave,replication client on *.*
    -> to rep@'192.168.129.%' identified by 'localhost';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> change master to
    -> master_host='192.168.129.128',
    -> master_user='rep',
    -> master_password='localhost',
    -> master_log_file='mysql-bin.000001',
    -> master_log_pos=0;
ERROR 1198 (HY000): This operation cannot be performed with a running slave; run STOP SLAVE first    #此處報錯需要停止SLAVE
MariaDB [(none)]> stop slave    #停止SLAVE
    -> ;
Query OK, 0 rows affected (0.01 sec)

MariaDB [(none)]> change master to master_host='192.168.129.128', master_user='rep', master_password='localhost', master_log_file='mysql-bin.000001', master_log_pos=0;
Query OK, 0 rows affected (0.02 sec)

MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: 
                  Master_Host: 192.168.129.128
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 4
               Relay_Log_File: mariadb-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: No
            Slave_SQL_Running: No

MariaDB [(none)]> slave start;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.129.128
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 493
               Relay_Log_File: mariadb-relay-bin.000002
                Relay_Log_Pos: 777
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

(4)測試:

  在 mysql1 節點創建數據庫,在 mysql2 節點查看:

  mysql1 節點:

MariaDB [(none)]> create database data1;
Query OK, 1 row affected (0.01 sec)

MariaDB [(none)]> create table data1.t1;
ERROR 1113 (42000): A table must have at least 1 column
MariaDB [(none)]> create table data1.t1(name int);
Query OK, 0 rows affected (0.02 sec)

MariaDB [(none)]> insert into data1.t1 values(1);
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> select * from data1.t1;
+------+
| name |
+------+
|    1 |
+------+

  mysql2 節點查看:

MariaDB [(none)]> select * from data1.t1;
+------+
| name |
+------+
|    1 |
+------+

  同理 mysql2 節點創建數據庫,mysql1 節點查看;至此實現 mysql 主主復制。

4、生產環境其他常用設置

4.1 配置忽略權限庫同步參數

binlog-ignore-db='information_schema mysql test'

4.2 從庫備份開啟 binlog

log-slave-updates
log_bin = mysql-bin
expire_logs_days = 7

應用場景:級聯復制或從庫做數據備份。

4.3 從庫只讀 read-only 來實現

innodb_read_only = ON

結論:當用戶權限中沒有SUPER權限(ALL權限是包括SUPER的)時,從庫的read-only生效!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM