MMM介紹
MMM是Multi-Master Replication Manager for MySQL的縮寫,它是MySQL提供的一個多主複製管理器,其核心是使用perl語言編寫的一組腳本。實際上MMM是比較早期甚至有點老的一種用於構建高可用MySQL架構的方式,但因其還有一定的應用場景,所以本文將會演示一下如何搭建一個MMM架構。
MMM 由兩個組件組成:
monitor
:監控集羣內數據庫的狀態,在出現異常時發佈切換命令,一般和數據庫分開部署agent
:運行在每個 MySQL 服務器上的代理進程,monitor
命令的執行者,完成監控的探針工作和具體服務設置,例如設置 VIP、指向新同步節點
MMM的主要作用:
- 監控和管理MySQL的主主複製拓撲,並在當前的主服務器發生故障時,進行主和主備服務器之間的主從切換和故障轉移等工作
MMM提供了什麼功能:
- MMM可以監控MySQL主從複製健康情況,包括mysql服務器的狀態、從庫拷貝活動的狀態等
- 可以在主庫出現宕機時進行故障轉移,並自動配置其他從庫對新主庫的複製
- 爲主庫提供了一個寫虛擬IP,在主從服務器出現問題時可以自動遷移虛擬IP
- 當配置多個從庫時,可配置多個虛擬讀IP,配合第三方負載均衡軟件(如LVS),實現負載均衡功能
MMM對於主備切換後如何讓從庫同步日誌點:
- MMM對於這方面的處理並不安全,只是簡單粗暴地讓從庫同步新主庫的當前日誌點,所以在一個繁忙的系統中使用MMM很有可能會對數據造成丟失的情況
動手搭建MMM架構
本文要搭建的MMM架構如下:
以上述架構爲例,描述一下故障轉移的流程,現在假設 Master1 宕機:
- Monitor 檢測到 Master1 連接失敗
- Monitor 發送 set_offline 指令到 Master1 的 Agent
- Master1 Agent 如果存活,下線寫 VIP,嘗試把 Master1 設置爲
read_only=1
- Moniotr 發送 set_online 指令到 Master2
- Master2 Agent 接收到指令,執行
select master_pos_wait()
等待同步完畢 - Master2 Agent 上線寫 VIP,把 Master2 節點設爲
read_only=0
- Monitor 發送更改同步對象的指令到各個 Slave 節點的 Agent
- 各個 Slave 節點向新 Master 同步數據
從整個流程可以看到,如果主節點出現故障,MMM 會自動實現切換,不需要人工干預,同時我們也能看出一些問題,就是數據庫掛掉後,只是做了切換,不會主動補齊丟失的數據,所以 MMM 會有數據不一致性的風險。
搭建MMM架構所需的資源說明:
名稱 | 數量 | 說明 |
---|---|---|
Master服務器 | 2 | 用於主備模式的主主複製配置 |
Slave服務器 | 0-N | 可以配置0臺或多臺從服務器,但不建議太多 |
監控服務器 | 1 | 安裝MMM用於監控MySQL複製集羣 |
IP地址 | 2*(n+1) | n爲MySQL服務器的數量 |
監控用戶 | 1 | 用於監控數據庫狀態的MySQL用戶(至少擁有replication client 權限) |
代理用戶 | 1 | 用於MMM代理的MySQL用戶(至少擁有super 、replication client 、process 權限) |
複製用戶 | 1 | 用於配置MySQL主從複製的用戶(至少擁有replication slave 權限) |
本文中所使用的機器說明:
名稱 | IP | 角色 |
---|---|---|
master-01 | 192.168.190.146 | 主庫 |
master-02 | 192.168.190.148 | 備庫 |
slave-01 | 192.168.190.149 | 從庫 |
manager | 192.168.190.147 | 集羣管理器(MMM) |
環境版本說明:
- 操作系統版本:CentOS 7
- MySQL版本:8.0.19
- MMM版本:2.2.1
另外的說明:
- 會來了解MMM架構的小夥伴們想必都已經掌握了MySQL的安裝方式,而且介紹MySQL的安裝也有很多文章,所以本文爲了減少不必要的篇幅就不演示MySQL的安裝了,文中所用到的機器都已經提前安裝好了MySQL。
配置主主複製及主從同步集羣
1、在master-01
和master-02
上使用如下語句分別創建用於主主複製的MySQL用戶:
create user 'repl'@'%' identified with mysql_native_password by 'Abc_123456';
grant replication slave on *.* to 'repl'@'%';
flush privileges;
- Tips:創建好賬戶後,最好使用該賬戶在兩個節點互相登錄一下,以確保賬戶是可用的
2、修改master-01
上的MySQL配置文件:
[root@master-01 ~]# vim /etc/my.cnf
[mysqld]
# 設置節點的id
server_id=101
# 開啓binlog,並指定binlog文件的名稱
log_bin=mysql_bin
# 開啓relay_log,並指定relay_log文件的名稱
relay_log=relay_bin
# 將relaylog的同步內容記錄到binlog中
log_slave_updates=on
在master-02
的配置文件中也是添加一樣配置,只不過server_id
不一樣:
[root@master-02 ~]# vim /etc/my.cnf
[mysqld]
server_id=102
log_bin=mysql_bin
relay_log=relay_bin
log_slave_updates=on
接着是配置slave-01
,由於該節點不是作爲備庫存在,而只是單獨的從庫角色,所以不需要開啓log_slave_updates
參數:
[root@slave-01 ~]# vim /etc/my.cnf
[mysqld]
server_id=103
log_bin=mysql_bin
relay_log=relay_bin
完成以上配置文件的修改後,分別重啓這三個節點上的MySQL服務:
[root@master-01 ~]# systemctl restart mysqld
[root@master-02 ~]# systemctl restart mysqld
[root@slave-01 ~]# systemctl restart mysqld
配置master-02
對master-01
的主從關係
進入master-01
的MySQL命令行終端,通過如下語句查詢master-01
當前正在使用的二進制日誌及當前執行二進制日誌位置:
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql_bin.000001 | 155 | | | |
+------------------+----------+--------------+------------------+-------------------+
記錄其中的File
和Position
的值,然後進入master-02
的MySQL命令行終端,分別執行如下語句:
mysql> stop slave; -- 停止主從同步
mysql> change master to master_host='192.168.190.146', master_port=3306, master_user='repl', master_password='Abc_123456', master_log_file='mysql_bin.000001', master_log_pos=155; -- 配置master-01節點的連接信息,以及從哪個binlog文件的哪個位置開始複製
mysql> start slave; -- 啓動主從同步
配置完主從關係後,使用show slave status\G;
語句查看主從同步狀態,Slave_IO_Running
和Slave_SQL_Running
的值均爲Yes
才能表示主從同步狀態是正常的:
配置master-01
對master-02
的主從關係
爲了實現主主複製,master-01
和master-02
需要互爲主從關係,所以還需要配置master-01
對master-02
的主從關係。進入master-02
的MySQL命令行終端,通過如下語句查詢master-02
當前正在使用的二進制日誌及當前執行二進制日誌位置:
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql_bin.000001 | 155 | | | |
+------------------+----------+--------------+------------------+-------------------+
記錄其中的File
和Position
的值,然後進入master-01
的MySQL命令行終端,分別執行如下語句:
mysql> stop slave;
mysql> change master to master_host='192.168.190.148', master_port=3306, master_user='repl', master_password='Abc_123456', master_log_file='mysql_bin.000001', master_log_pos=155;
mysql> start slave;
同樣配置完成後,使用show slave status\G;
語句查看主從同步狀態,Slave_IO_Running
和Slave_SQL_Running
的值均爲Yes
才能表示主從同步狀態是正常的:
配置slave-01
對master-01
的主從關係
接着就是配置從庫對主庫的主從關係了,這裏與master-02
是一樣的,除非期間對master-01
上的數據做了修改才需要重新獲取日誌點:
mysql> stop slave;
mysql> change master to master_host='192.168.190.146', master_port=3306, master_user='repl', master_password='Abc_123456', master_log_file='mysql_bin.000001', master_log_pos=155;
mysql> start slave;
搭建MMM服務
1、在所有的機器上安裝 epel
源:
yum install -y epel-release
2、在所有的主從節點上安裝MMM代理客戶端:
yum install -y mysql-mmm-agent
3、在 manager
節點上安裝所有的MMM包:
yum install -y mysql-mmm*
4、然後在master-01
上創建用於監控和代理的MySQL用戶:
-- 監控用戶
create user 'mmm_monitor'@'%' identified with mysql_native_password by 'Abc_123456';
grant replication client on *.* to 'mmm_monitor'@'%';
-- 代理用戶
create user 'mmm_agent'@'%' identified with mysql_native_password by 'Abc_123456';
grant super, replication client, process on *.* to 'mmm_agent'@'%';
flush privileges;
由於配置了主從的原因,此時其他兩個數據庫節點也會同步這些新建的用戶。在另外兩個節點執行如下語句就可以查詢到:
mysql> use mysql;
mysql> select host,user,plugin from user;
+-----------+------------------+-----------------------+
| host | user | plugin |
+-----------+------------------+-----------------------+
| % | mmm_agent | mysql_native_password |
| % | mmm_monitor | mysql_native_password |
| % | repl | mysql_native_password |
| localhost | mysql.infoschema | caching_sha2_password |
| localhost | mysql.session | caching_sha2_password |
| localhost | mysql.sys | caching_sha2_password |
| localhost | root | caching_sha2_password |
+-----------+------------------+-----------------------+
5、編輯所有節點包括監控節點上的mmm_common.conf
配置文件,主要是配置當前節點和集羣中其他節點的信息。這裏以master-01
節點爲例,其配置內容如下:
[root@master-01 ~]# vim /etc/mysql-mmm/mmm_common.conf
active_master_role writer
<host default>
cluster_interface ens32 # 當前節點的網卡名稱,用於綁定虛擬IP,可以ip addr命令查詢
pid_path /run/mysql-mmm-agent.pid # pid文件存放的路徑
bin_path /usr/libexec/mysql-mmm/ # 可執行文件存放的路徑
replication_user repl # 用於複製的MySQL用戶
replication_password Abc_123456 # repl用戶的密碼
agent_user mmm_agent # 用於代理的MySQL用戶
agent_password Abc_123456 # mmm_agent用戶的密碼
</host>
# 配置master-01的ip地址和角色
<host db1>
ip 192.168.190.146
mode master
peer db2
</host>
# 配置master-02的ip地址和角色
<host db2>
ip 192.168.190.148
mode master
peer db1
</host>
# 配置slave-01的ip地址和角色
<host db3>
ip 192.168.190.149
mode slave
</host>
# 配置負責寫操作的庫
<role writer>
hosts db1, db2 # 指定可寫的庫,這裏是上面host標籤中定義的名稱
ips 192.168.190.90 # 配置寫虛擬IP,可以有多個使用逗號分隔
mode exclusive # 表示同一時刻只有一個主庫提供服務
</role>
# 配置負責讀操作的庫
<role reader>
hosts db1, db2, db3 # 指定可讀的庫
ips 192.168.190.91,192.168.190.92,192.168.190.93 # 配置讀虛擬IP
mode balanced # 表示將讀請求負載均衡到以上所配置的db上
</role>
其他三個節點也按照相同的方式進行配置即可,除了網卡名稱可能會不同外,其它的參數都應該是一致的。
6、然後配置各個節點的mmm_agent.conf
文件,聲明當前節點在host
標籤中所定義的名稱。master-01
節點的配置如下:
[root@master-01 ~]# vim /etc/mysql-mmm/mmm_agent.conf
include mmm_common.conf
this db1
master-02
節點的配置如下:
[root@master-02 ~]# vim /etc/mysql-mmm/mmm_agent.conf
include mmm_common.conf
this db1
slave-01
節點的配置如下:
[root@slave-01 ~]# vim /etc/mysql-mmm/mmm_agent.conf
include mmm_common.conf
this db3
7、接着配置監控節點上的mmm_mon.conf
文件,配置內容如下:
[root@manager ~]# vim /etc/mysql-mmm/mmm_mon.conf
include mmm_common.conf
<monitor>
ip 127.0.0.1
pid_path /run/mysql-mmm-monitor.pid
bin_path /usr/libexec/mysql-mmm
status_path /var/lib/mysql-mmm/mmm_mond.status
ping_ips 192.168.190.146,192.168.190.148,192.168.190.149 # 配置集羣中各個節點的IP
auto_set_online 60 # 設置當節點宕機恢復後自動上線的時間,單位爲秒
# The kill_host_bin does not exist by default, though the monitor will
# throw a warning about it missing. See the section 5.10 "Kill Host
# Functionality" in the PDF documentation.
#
# kill_host_bin /usr/libexec/mysql-mmm/monitor/kill_host
#
</monitor>
<host default>
# 配置用於監控的MySQL用戶和密碼
monitor_user mmm_monitor
monitor_password Abc_123456
</host>
debug 0
8、啓動所有主從節點的MMM代理服務:
[root@master-01 ~]# systemctl start mysql-mmm-agent
[root@master-02 ~]# systemctl start mysql-mmm-agent
[root@slave-01 ~]# systemctl start mysql-mmm-agent
agent
服務默認會監聽9989
端口,如果開啓了防火牆則需要開放該端口:
firewall-cmd --zone=public --add-port=9989/tcp --permanent
firewall-cmd --reload
9、啓動監控節點上的監控服務:
[root@manager ~]# systemctl start mysql-mmm-monitor
10、完成以上所有步驟後,在監控節點上使用mmm_control show
命令就可以查看到集羣中各個節點的狀態及其分配的虛擬IP,如下示例:
[root@manager ~]# mmm_control show
db1(192.168.190.146) master/ONLINE. Roles: reader(192.168.190.91), writer(192.168.190.90)
db2(192.168.190.148) master/ONLINE. Roles: reader(192.168.190.93)
db3(192.168.190.149) slave/ONLINE. Roles: reader(192.168.190.92)
[root@manager ~]#
測試
到此爲止,我們就已經完成了MMM高可用架構的搭建,接下來我們對其進行一些簡單的測試。例如,測試下是否能正常ping
通虛擬IP,畢竟應用端訪問數據庫時連接的是虛擬IP,所以首先得確保虛擬IP是能夠被訪問的。如下:
能ping
通之後,使用Navicat等遠程連接工具測試下能否正常連接上:
確定了各個虛擬IP都能正常訪問後,測試下MMM是否能正常進行故障轉移,首先將master-01
上的MySQL服務給停掉:
[root@master-01 ~]# systemctl stop mysqld
正常情況下,此時到監控節點上使用mmm_control show
命令可以看到master-01
節點已經處於脫機狀態,而用於寫的虛擬IP正常的切換到了master-02
節點上:
[root@manager ~]# mmm_control show
db1(192.168.190.146) master/HARD_OFFLINE. Roles:
db2(192.168.190.148) master/ONLINE. Roles: reader(192.168.190.93), writer(192.168.190.90)
db3(192.168.190.149) slave/ONLINE. Roles: reader(192.168.190.91), reader(192.168.190.92)
[root@manager ~]#
接着進入slave-01
節點上的MySQL終端。之前我們配置slave-01
的主庫是master-01
,現在已經將master-01
停掉後,可以看到slave-01
的主庫被MMM切換成了master-02
:
經過以上測試後,可以看到我們搭建的MMM架構是能夠正常運行的,已經使得Replication集羣擁有了基本的高可用能力,即便主庫下線後也能正常切換到備庫上,也正確建立了從庫與新主庫的關係。
MMM架構的優缺點
優點:
- 使用Perl腳本語言開發並且完全開源,開發者可以根據自己的需求進行二次開發
- 提供了從服務器的延遲監控以及讀寫VIP(虛擬IP),使服務器角色的變更對前端應用透明。並且在從庫出現大量的主從延遲或主從複製鏈路中斷時,可以把這臺從庫上的讀虛擬IP,漂移到集羣中其他正常的可讀節點上
- 提供了當主庫故障轉移後,從庫對新主庫的重新同步功能,所以很容易對發生故障的主庫重新上線,讓Replication集羣具備高可用性
缺點:
- MMM屬於一個比較老的工具了,其最後發佈的版本也是好幾年前了,所以會存在一些小bug,並且不支持MySQL 5.6+版本中新增的基於GTID的複製,只支持基於日誌點的複製
- 沒有提供讀負載均衡的功能,需要額外引入LVS等工具來實現
- 在進行主從切換時,容易造成數據丟失或事務的重複提交。因爲MMM不會對比多個從庫的日誌點,而是直接選擇備庫進行切換。由於Replication集羣是異步複製的,當備庫的同步延遲比較大時,可能會出現從庫的日誌點比備庫的要更新。所以當主庫意外下線時,MMM強制切換成備庫就有可能會導致數據的丟失或從庫重複提交事務
- MMM沒有提供相關的高可用功能,所以監控節點自身存在單點故障,而Replication集羣的高可用依賴於監控節點,當監控節點掛掉Replication集羣也就不再具備高可用性了。但我們可以引入第三方工具來對監控節點做雙機熱備,例如Keepalived
綜合優缺點可以得知:MMM僅適用於對數據一致性要求不高,允許丟失少量數據的場景下,例如評論、資訊類等數據