Home MariaDB Master-Slave Replication with MaxScale
Post
Cancel

MariaDB Master-Slave Replication with MaxScale

最近因工作關係剛好研究到 MariaDB High Availability (HA) 機制,因此本篇整理一下 MariaDB Master-Slave Replication 的相關筆記。

在一個系統環境裡,資料庫通常扮演著很重要的角色,主要負責存放系統的一些紀錄或是使用者的資料,因此資料庫的備援/高可用性 (High Availability)以及負載平衡 (Load Balancing) 就變得相當重要。

目前 MariaDB 針對 High Availability 有以下常見的幾種方式:

  • Master-Slave Replication (A-S Mode)
  • Master-Master Replication (A-A Mode)
  • Galera Cluster Master-Master (A-A Mode)
  • Galera Cluster Master-Slave (A-S Mode)

本篇文章主要會探討的是最傳統的方式 Master-Slave Replication

Master-Slave Replication

Master-Slave Replication 主要是將多台 MariaDB 組成 Cluster,而這個 Cluster 裡,會有一台 MariaDB 扮演 Master 的角色,而其他 1~n 台會扮演著 Slave 的角色,Master 主要負責的動作為Read-Write;Slave 則負責 Read 以及同步 Master 的所有操作。

以下為最常見的架構,通常 Master 只會有一台,然後會有多台 Slave 不斷同步 Master 的工作,當 Master 掛掉時,管理者可以將 Slave 轉換成 Master 取代 Master 動作。

圖片來源: Replication Overview

因此在這種 Master-Slave Replication 架構下:

  1. 只能有一台 Master 存在,Master 可以處理 Read-Write 工作
  2. 可以有多台 Slave 存在,Slave 可以處理 Read 工作或是單純 Standby
  3. Slave 會不斷跟 Master 同步資料
  4. 支援 Read HA + LoadBalancing
  5. 支援 Write HA 但不支援 Load Balancing

💡 如果要考量 Write Load Balancing,就必須要有多台 Master 同時運作的情境,這種情境就要改使用 Master-Master Replication 或是 MariaDB Galera Cluster。

同步機制

圖片來源: HA for MySQL and MariaDB - Comparing Master-Master Replication to Galera Cluster

MariaDB Replication 主要透過 Binary Log 以及 Relay Log 的方式進行同步。

  1. Master 會將 CREATEALTERINSERTUPDATE 還有 DELETE 這些操作的步驟記錄在 BInary Log 裡面。
  2. Slave 會定期 Polling Master Binary Log (使用 MySQL API, 這間隔趨近 Real-Time),並將 Binary Log 資訊以及同步紀錄寫在自己的 Relay Log 裡面。
  3. Slave 最後根據 Relay Log 資訊來套用 SQL 到 Slave MariaDB 上。
  4. 完成同步。

設定步驟

此文章採用版本資訊如下:

  • MariaDB 10.3.32
  • Ubuntu 20.04 LTS

環境:

  • Master MariaDB 192.168.89.131
  • Slave MariaDB 192.168.89.132

以下步驟開始在 Master MariaDB 上操作

  1. 設定 my.cnf 檔,啟用 Binary Log
    1
    2
    
    mkdir /root/config
    touch /root/config/my.cnf
    

    my.cnf (在 Master-Slave Replication Cluster 裡,每台 MariaDB server_id 需要不一樣)

    1
    2
    3
    4
    5
    
     [mariadb]
     log-bin
     server_id=1
     log-basename=master1
     binlog-format=mixed
    
  2. 部署 Master MariaDB
    1
    2
    3
    
     export IP=192.168.89.131
    
     docker run --name mariadb-master -p $IP:3306:3306 -v /root/config:/etc/mysql/conf.d -e MARIADB_ROOT_PASSWORD=123456 -d mariadb:10.3.32
    

    此指令為測試用,若是在 Production,請記得設定加上 Persistent Data 存放目錄以及相關帳號設定,不要使用 Root。

  3. 建立 Replication 用的帳號
    1
    2
    3
    
     docker exec -it mariadb-master bash
    
     $ mysql -u root -p123456
    
    1
    2
    3
    
     MariaDB [(none)]> GRANT REPLICATION SLAVE ON *.* to replicator@'%' IDENTIFIED BY 'secret';
     MariaDB [(none)]> FLUSH PRIVILEGES;
     MariaDB [(none)]> FLUSH TABLES WITH READ LOCK;
    
  4. 查看 Master 資訊,需記下 Binary Log 名稱
    1
    2
    3
    4
    5
    6
    7
    
    MariaDB [(none)]> SHOW MASTER STATUS;
    +          +      +        +          +
    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +          +      +        +          +
    | master1-bin.000003 | 466 | | |
    +          +      +        +          +
    1 row in set (0.00 sec)
    

    以下步驟開始在 Slave MariaDB 上操作

  5. 設定 my.cnf 檔,啟用 Binary Log
    1
    2
    
     mkdir /root/config
     touch /root/config/my.cnf
    

    my.cnf (在 Master-Slave Replication Cluster 裡,每台 MariaDB server_id 需要不一樣)

    1
    2
    
     [mariadb]
     server_id=2
    
  6. 部署 Slave MariaDB 。
    1
    2
    3
    
     export IP=<slave node IP>
    
     docker run --name mariadb-slave -p $IP:3306:3306 -v /root/config:/etc/mysql/conf.d -e MARIADB_ROOT_PASSWORD=123456 -d mariadb:10.3.32
    

    此指令為測試用,若是在 Production,請記得設定加上 Persistent Data 存放目錄以及相關帳號設定,不要使用 Root。

  7. 設定連到 Master MariaDB,並啟用 Slave 服務, CHANGE MASTER 根據 Master 資訊填寫。
    1
    2
    3
    
     docker exec -it mariadb-slave bash
    
     $ mysql -u root -p123456
    
    1
    2
    3
    
     MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.89.131', MASTER_USER='replicator', MASTER_PASSWORD='secret', MASTER_LOG_FILE='master1-bin.000003', MASTER_LOG_POS=466;
    
     MariaDB [(none)]> START SLAVE;
    

    MASTER_LOG_FILE 代表要去讀 Master 的 Binary Log 名稱
    MASTER_LOG_POS 代表要從 Binary Log 哪一個位置開始同步,需跟 SHOW MASTER STATUS;Position 值一樣。

  8. 查看 Slave 資訊 (需確認 Slave_IO_Running 以及 Slave_SQL_Running 是否為 Yes)
    1
    
     MariaDB [(none)]> SHOW SLAVE STATUS;
    

    以下步驟開始在 Master MariaDB 上操作

  9. UNLOCK Master MariaDB Table。
    1
    
    MariaDB [(none)]> UNLOCK TABLE ;
    
  10. 這樣就完成,可以嘗試看看透過 Master 進行寫入動作,Slave 那邊是否會同步。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    MariaDB [(none)]> CREATE DATABASE hello;
    MariaDB [(none)]> USE hello;
    MariaDB [hello]>  CREATE TABLE hellotable (`id` int, `name` varchar(10) ) ;
    MariaDB [hello]> INSERT INTO hellotable (`id`,`name`) VALUES ('1','pohsien') ;
    
    MariaDB [hello]> SELECT * FROM hellotable;
    +------+---------+
    | id   | name    |
    +------+---------+
    |    1 | pohsien |
    +------+---------+
    1 row in set (0.000 sec)
    

    以下步驟開始在 Slave MariaDB 上操作

  11. 在 Slave 可以馬上看到剛剛在 Master 建立的 DB、Table 以及 Record。
    1
    2
    3
    4
    5
    6
    7
    8
    
    MariaDB [(none)]> USE hello;
    MariaDB [hello]> SELECT * FROM hellotable;
    +------+---------+
    | id   | name    |
    +------+---------+
    |    1 | pohsien |
    +------+---------+
    1 row in set (0.000 sec)
    
  12. 後續可以搭配 HA Proxy 以及程式端設定讀寫分離,讓程式寫入資料時到 Master 上去寫,要讀的時候,就透過 HA Proxy Load Balancing 到任一台 Slave 去讀,可以提高效率以及增加高可用性。

💡 請注意,在 Master-Slave Replication 中同步是單向的,也就是只能 Master 同步給 Slave,並不能 Slave 同步給 Master,如果不小心在 Slave 寫入資料,會造成 split-brain 的嚴重情況,Cluster 同步會出問題。

Auto-Failover

MariaDB Master-Slave Replication 預設不支援動態 Failover,如果遇到 Master 故障,需要手動進行切換,將 Slave 啟用 binlog,讓他變成 Master,然後剩下的 Slave 必須設定 CHANGE MASTER 來將他指到新的 Master,皆需要管理者手動設定。

另外在 Load Balancer 端,像 HA Proxy 這類型的 Load Balancer,也很難自動根據 MariaDB Master 或 Slave 角色變換調整 Server Pool,步驟相當繁瑣。

因此 MariaDB 官方釋出一個工具 MaxScale,他裡面包含了許多模組,例如 Monitor 模組,可以監看 MariaDB Cluster 狀態,並實現 auto-failover 以及 auto-rejoin (掛掉的 Node 恢復後主動加回 Cluster)。 Service 模組,可以實現路由,將流量導到正確身份的 MariaDB 身上,當有 Failover 發生後,也可以自動轉換流量導向,非常方便。

MaxScale 設定步驟

此文章採用版本資訊如下:

  • MariaDB 10.3.32
  • Ubuntu 20.04 LTS
  • MaxScale 6.2.1

環境(總共有四台 VM):

  • Master MariaDB 192.168.89.131 (server_id: 1)
  • Slave MariaDB-1 192.168.89.132 (server_id: 2)
  • Slave MariaDB-2 192.168.89.133 (server_id: 3)
  • MaxScale 192.168.89.134
  1. 參考 MariaDB MaxScale Installation Guide 安裝 MaxScale 以及設定完 MariaDB Master-Slave Cluster。
  2. 在 MaxScale VM 編輯 MaxScale 設定檔
    1
    
    $ vim /etc/maxscale.cnf
    
  3. 建立三台 MariaDB 資訊, [] 名稱可以任意取名,這邊設定很像設定 Load Balancer 的 Server Pool (Backend) 一樣。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
     ...
     [server1]
     type=server
     address=192.168.89.131
     port=3306
     protocol=MariaDBBackend
    
     [server2]
     type=server
     address=192.168.89.132
     port=3306
     protocol=MariaDBBackend
    
     [server3]
     type=server
     address=192.168.89.133
     port=3306
     protocol=MariaDBBackend
     ...
    
  4. 設定 Monitor,監控 MariaDB 的狀態,其中這裡也可以設定 auto_failover 以及 auto_rejoin 來實現 Master 身份自動轉移以及自動將排除異常的 Node 重新加回 Cluster。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    ...
    [MariaDB-Monitor]
    type=monitor
    module=mariadbmon
    servers=server1,server2,server3
    user=root
    password=123456
    monitor_interval=2000
    # 啟用自動 Failover
    auto_failover=true
    # 啟用自動 rejoin
    auto_rejoin=true
    ...
    
  5. 設定 Service (路由),預設是讀寫分開,這邊可以設定 Listener 以及 Backend,可以將讀寫切分成不同的 Listener,並對應到不同的 Backend。

    在此我們將 Write 的動作都導向到 Master MariaDB 身上,Read 的動作則導向到 Slave MariaDB 身上,MaxScale 會自己判斷身份,所以只要將全部 MariaDB 都加進 Service 就好。

    若要讀寫分開也必須看自己的 Application 是否有支援這樣設計

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    
     ...
    
     #--------- Services (LoadBalancr 後端的 Server Pool) ----------
    
     ## 給 Reqd-Only 使用
     [Read-Only-Service]
     type=service
     router=readconnroute
     # 這邊設定要當作 Backend 的 Server
     servers=server1,server2,server3
     user=maxscale
     password=123456
     # 設定要作為 Backend 的種類,這裡表示會從 servers Group 裡面挑出 Slave 來做 LoadBalancing
     router_options=slave
    
     ## 給 Read-Write 使用 
     [Read-Write-Service]
     type=service
     router=readconnroute
     # 這邊設定要當作 Backend 的 Server
     servers=server1,server2,server3
     user=maxscale
     password=123456
     # 設定要作為 Backend 的種類,這裡表示會從 servers Group 裡面挑出 Master 來做 LoadBalancing
     router_options=master
    
     #----------- Listeners (LoadBalancr 前端的窗口) --------------
     [Read-Only-Listener]
     type=listener
     service=Read-Only-Service
     protocol=MariaDBClient
     address=192.168.89.134
     port=4008
    
     [Read-Write-Listener]
     type=listener
     service=Read-Write-Service
     protocol=MariaDBClient
     port=4006
     address=192.168.89.134
     ...
    

    💡 這邊的 user password 是給 MaxScale 使用的,因為 MaxScale 主要接收 Client 連線的窗口,所以他會需要權限能夠讀 MariaDB 的 User 資訊以及連到 MariaDB 去做一些操作,例如修改 Master-Slave 設定,可查看 Creating a user account for MaxScale

  6. 完成後重啟 MaxScale,這樣設定完之後,連線資訊如下:
    • Read 使用的連線資訊: 192.168.89.134:4008
    • Write 使用的連線資訊: 192.168.89.134.4006
    1
    
     $ systemctl restart maxscale.service
    
  7. 在 MaxScale VM 查看 Monitor 資訊,如果把 Master 關機,可以看到 State 切換,也可以參考 Manual Failover 手動切換角色 maxctrl call command mariadbmon failover Monitor
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    $ maxctrl list servers
    ┌─────────┬────────────────┬──────┬─────────────┬─────────────────┬──────────┐
    │ Server  │ Address        │ Port │ Connections │ State           │ GTID     │
    ├─────────┼────────────────┼──────┼─────────────┼─────────────────┼──────────┤
    │ server1 │ 192.168.89.131 │ 3306 │ 0           │ Master, Running │ 0-3-7224 │
    ├─────────┼────────────────┼──────┼─────────────┼─────────────────┼──────────┤
    │ server2 │ 192.168.89.132 │ 3306 │ 0           │ Slave, Running  │ 0-3-7224 │
    ├─────────┼────────────────┼──────┼─────────────┼─────────────────┼──────────┤
    │ server3 │ 192.168.89.133 │ 3306 │ 0           │ Slave, Running  │ 0-3-7224 │
    └─────────┴────────────────┴──────┴─────────────┴─────────────────┴──────────┘
    
  8. 透過 MaxScale 存取 MariaDB 測試 LoadBalancing 是否正確。
    1
    2
    
    $ msql -h 192.168.89.134 -P 4006 -u myuser -p
    $ msql -h 192.168.89.134 -P 4008 -u myuser -p
    

    💡 這邊的使用者是給 application 連線用的,這個需要注意,因為連線方式是: clientmaxscalemariadb ,所以需要設定這個使用者能從 client 端以及 maxscale 連到 MariaDB,可參考 Creating client user accounts

  9. 若透過 4006 port 成功連到 MariaDB,查看連到的 DB Server id,應該不管在哪裡連都會是 Master 那台 Node。
    1
    2
    3
    4
    5
    6
    
    MariaDB [(none)]> SELECT @@server_id ;
    +-------------+
    | @@server_id |
    +-------------+
    |           1 |
    +-------------+
    
  10. 若透過 4008 port 成功連到 MariaDB,查看連到的 DB Server id,應該會是任一台 Slave 。
    1
    2
    3
    4
    5
    6
    
    MariaDB [(none)]> SELECT @@server_id ;
    +-------------+
    | @@server_id |
    +-------------+
    |           3 |
    +-------------+
    

MaxScale with Keepalived

由於 MaxScale 會不斷偵測 MariaDB 異常以及提供 Load Balancing,如果 MaxScale 本身異常的話,會導致這些機制停掉,因此在 Production 環境 通常需要多台來達到 HA。

MariaDB 官方採用 Keepalived 來實現 MaxScale HA,可以參考 MaxScale HA setup using Keepalived and MaxCtrl

圖片來源: MaxScale HA setup using Keepalived and MaxCtrl

參考資料

Introduction

Setup Replication

MaxScale

文章內容的轉載、重製、發佈,請註明出處: https://pohsienshih.github.io

This post is licensed under CC BY 4.0 by the author.

2021 個人年度回顧

ActiveMQ 5 Shared File System Master Slave