上一篇博文我們使用keepalived+主從同步搭建了一個簡單的MySQL高可用架構(詳見http://blog.51cto.com/jiangjianlong/1981994),今天再分享下通過MMM搭建的實現MySQL讀寫分離的高可用羣集。MMM (Master-Master Replication Manager for MySQL)是使用perl開發的MySQL主主複製管理器,可實現讀寫分離的高可用架構,對主庫實現寫請求的高可用,對從庫實現讀請求的負載均衡。本文的架構示意圖如下:
一、部署環境
二、環境準備
1、配置好IP地址、主機名,關閉防火牆和selinux
2、分別爲mysql-master01、mysql-master02、mysql-slave01、mysql-slave02安裝MySQL 5.6,安裝方法請參見本文之前的博文《MySQL 5.6.38在RedHat 6.5上通過RPM包安裝》,需要注意的是要安裝Mysql-devel的rpm包。
3、爲5臺服務器配置好hosts解析:
192.168.10.81 mysql-master01
192.168.10.82 mysql-master02
192.168.10.83 mysql-slave01
192.168.10.84 mysql-slave02
192.168.10.85 mysql-monitor
4、將RedHat 6.5的介質配置成本地yum源
三、配置兩臺master互爲主從
1、編輯mysql-master01和mysql-master02的/etc/my.cnf文件並重啓mysql服務:
mysql-master01:
[mysqld] server-id=1 #每臺設置不同 log-bin=mysql-bin [mysqld_safe] auto_increment_increment=2 #字段一次遞增多少 auto_increment_offset=1 #自增字段的起始值,master02需設置爲2 replicate-do-db=all #同步的數據庫,多個用逗號隔開 log-slave_updates #當一個主故障,另一個立即接管 sync-binlog=1 #每條自動更新,安全性高,默認是0 log-error = /var/log/mysqld.log read_only = 1
mysql-master02:
[mysqld] server-id=2 #每臺設置不同 log-bin=mysql-bin [mysqld_safe] auto_increment_increment=2 #字段一次遞增多少 auto_increment_offset=2 #自增字段的起始值,master02需設置爲2 replicate-do-db=all #同步的數據庫,多個用逗號隔開 log-slave_updates #當一個主故障,另一個立即接管 sync-binlog=1 #每條自動更新,安全性高,默認是0 log-error = /var/log/mysqld.log read_only = 1
2、在mysql-master01上創建用於同步的賬戶repl,密碼爲123456,並查詢master狀態,記下file名稱和posttion數值
mysql> GRANT REPLICATION SLAVE ON *.* to 'repl'@'%' identified by '123456';
mysql> show master status;
3、在mysql-master02上登錄mysql,執行以下語句開啓從服務器
mysql> change master to master_host='192.168.10.81',master_user='repl',master_password='123456',master_log_file='mysql-bin.000003',master_log_pos=318;
mysql> start slave;
mysql> show slave status\G
4、然後在mysql-master02上也創建用於同步的賬戶repl,密碼爲123456,並查詢master狀態,記下file名稱和posttion數值
mysql> GRANT REPLICATION SLAVE ON *.* to 'repl'@'%' identified by '123456';
mysql> show master status;
5、在mysql-master01上登錄mysql執行以下語句開啓從服務器,注意這裏master_host要填寫mysql-master02的IP
mysql> change master to master_host='192.168.10.82',master_user='repl',master_password='123456',master_log_file='mysql-bin.000006',master_log_pos=318;
mysql> start slave;
mysql> show slave status\G
6、這樣兩臺master的互爲主從就配置好了,下面我們來測試一下,先做mysql-master01上執行以下語句創建一個數據庫、一個表並插入一行數據
mysql> create database names_test;
mysql> use names_test;
mysql> create table names(id int(5),name char(15));
mysql> insert into names values (01,'jiangjianlong');
mysql> select * from names;
7、然後到mysql-master02上查詢一下,發現已經同步完成了,說明mysql-master02作爲mysql-master01的從庫複製正常
8、在mysql-master02上也創建一個數據庫、一個表並插入一行數據
mysql> create database blogs_test;
mysql> use blogs_test;
mysql> create table blogs(id int(5),name char(35));
mysql> insert into blogs values (01,'jiangjianlong.blog.51cto.com');
mysql> select * from names;
9、在mysql-master01上查詢一下,發現數據也已經同步過來,說明mysql-master01作爲mysql-master02的從庫也是複製正常
四、配置兩臺slave作爲master01的從庫
1、mysql-slave01和mysql-slave02分別使用以下my.cnf
mysql-slave01:
[mysqld] server-id=3 #每臺設置不同 log-bin=mysql-bin [mysqld_safe] replicate-do-db=all log-error = /var/log/mysqld.log read_only = 1
mysql-slave02:
[mysqld] server-id=4 #每臺設置不同 log-bin=mysql-bin [mysqld_safe] replicate-do-db=all log-error = /var/log/mysqld.log read_only = 1
2、根據在mysql-master01上執行show master status查出來的結果,在mysql-slave01和mysql-slave02上分別執行以下sql語句,開啓從服務器:
mysql> change master to master_host='192.168.10.81',master_user='repl',master_password='123456',master_log_file='mysql-bin.000004',master_log_pos=120;
mysql> start slave;
mysql> show slave status\G
五、安裝MMM要求的Perl模塊
1、MMM對所有MySQL節點所要求的Perl模塊如下:
2、以下以mysql-master01爲例進行perl模塊的安裝,另外3臺MySQL服務器同理。首先查看一下這些perl模塊還有哪些沒裝:
perldoc -l Algorithm::Diff DBI DBD::mysql File::Basename File::stat Log::Dispatch Log::Log4perl Mail::Send Net::ARP Proc::Daemon Time::HiRes
3、部分缺失的perl模塊在Redhat6.5的介質中有,可以通過本地yum源的方式安裝
[root@mysql-master01 ~]# yum install perl-DBI perl-DBD-mysql perl-MailTools perl-Time-HiRes perl-CPAN -y
4、使用以下命令再查看一下安裝結果
perldoc -l Algorithm::Diff DBI DBD::mysql File::Basename File::stat Log::Dispatch Log::Log4perl Mail::Send Net::ARP Proc::Daemon Time::HiRes
5、剩下的幾個perl模塊安裝起來稍微麻煩一點,可以使用源碼包編譯安裝,也可以使用cpan在線自動下載安裝,並能處理各模塊間的依賴關係。我一開始是嘗試去下載源碼包後手動進行編譯安裝,然而我在編譯到Log::Dispatch時我直接放棄這種方式了,因爲它依賴於很多個其它的perl模塊,而這些模塊可能又依賴於別的多個模塊!如下圖:
6、所以我決定使用cpan在線自動安裝的方式,但需要服務器能連外網。由於使用cpan安裝Algorithm::Diff時會告警提示YAML沒有安裝,因此我先使用cpan安裝YAML,而安裝YAML時會把它所依賴的Algorithm::Diff給裝上
7、接着執行cpan Log::Dispatch安裝Log::Dispatch,沒想到在自動下載安裝了50多個依賴模塊後還是報錯提示有多個依賴的模塊缺失,如下圖:
8、解決辦法:依次使用cpan安裝上圖所示的缺少的模塊,然後再執行cpan Log::Dispatch就能成功安裝上,如果cpan安裝Params::ValidationCompiler時報錯,就單獨下載這個模塊的源碼包進行編譯安裝
9、執行cpan Log::Log4perl安裝Log::Log4perl模塊、執行cpan Net::ARP安裝Net::ARP模塊、執行cpan Proc::Daemon安裝Proc::Daemon模塊
10、再來查看下所需perl模塊的安裝結果,這下已經全部都裝好了
11、monitor服務器也對perl模塊有要求,如下圖:
12、同樣是使用cpan安裝這些模塊,在此不再贅述。4臺mysql服務器和monitor服務器的perl模塊都安裝完成後,我們就可以來安裝配置MMM了
六、MySQL-MMM安裝配置
1、MMM對MySQL用戶的要求如下:
2、由於本文未使用到MMM tools,因此只需創建前3個用戶,由於前面已經做好了主從同步,因此只需要在mysql-master01上創建即可同步到另外3臺MySQL服務器
GRANT REPLICATION CLIENT ON *.* TO 'mmm_monitor'@'192.168.10.%' IDENTIFIED BY 'monitor';
GRANT SUPER,REPLICATION CLIENT,PROCESS ON *.* TO 'mmm_agent'@'192.168.10.%' IDENTIFIED BY'agent';
GRANT REPLICATION SLAVE ON *.* TO 'mmm_repl'@'192.168.10.%' IDENTIFIED BY'repl';
注:其實用戶mmm_repl可以不用建,因爲前面我們配置主從同步時已經建了一個repl用戶可供使用
3、使用以下語句檢查另外3臺MySQL服務器是否已同步了這3個用戶,可以看到都已經有了
select user,host from mysql.user where user in ('mmm_monitor','mmm_agent','mmm_repl');
4、在4臺MySQL服務器和monitor服務器上編譯安裝MMM,下面以mysql-master01爲例
[root@mysql-master01 ~]# tar -zxf mysql-mmm-2.2.1.tar.gz -C /usr/
[root@mysql-master01 ~]# cd /usr/mysql-mmm-2.2.1/
[root@mysql-master01 mysql-mmm-2.2.1]# make install
5、安裝完成後,所有的配置文件都放到了/etc/mysql-mmm/下面。monitor服務器和MySQL服務器上都要包含一個共同的文件mmm_common.conf,內容如下:
[root@mysql-master01 mysql-mmm-2.2.1]# cat /etc/mysql-mmm/mmm_common.conf active_master_role writer <host default> cluster_interface eth0 pid_path /var/run/mmm_agentd.pid bin_path /usr/lib/mysql-mmm/ replication_user mmm_repl replication_password repl agent_user mmm_agent agent_password agent </host> <host mysql-master01> ip 192.168.10.81 mode master peer mysql-master02 </host> <host mysql-master02> ip 192.168.10.82 mode master peer mysql-master01 </host> <host mysql-slave01> ip 192.168.10.83 mode slave </host> <host mysql-slave02> ip 192.168.10.84 mode slave </host> <role writer> hosts mysql-master01, mysql-master02 ips 192.168.10.91 mode exclusive </role> <role reader> hosts mysql-slave01, mysql-slave02 ips 192.168.10.93, 192.168.10.94 mode balanced </role> [root@mysql-master01 mysql-mmm-2.2.1]#
6、在mysql-master01上編輯好該文件後,通過scp傳輸到另外4臺服務器
7、4臺MySQL服務器還有一個mmm_agent.conf文件需要修改主機名
8、在4臺MySQL服務器的 /etc/init.d/mysql-mmm-agent的腳本文件的#!/bin/sh下面,加入如下內容
source /root/.bash_profile,下面以mysql-master01爲例
9、分別將4臺MySQL服務器的mmm_agent啓動腳本添加成系統服務並設置爲自啓動,下面以mysql-master01爲例
#chkconfig --add mysql-mmm-agent
#chkconfig mysql-mmm-agent on
10、分別將4臺MySQL服務器的mmm_agent啓動,如果前面的Perl模塊沒有裝好,可能會報錯啓動不了
/etc/init.d/mysql-mmm-agent start或service mysql-mmm-agent start
11、配置monitor服務器上的mmm_mon.conf文件
[root@mysql-monitor mysql-mmm]# cat/etc/mysql-mmm/mmm_mon.conf include mmm_common.conf <monitor> ip 127.0.0.1 pid_path /var/run/mmm_mond.pid bin_path /usr/lib/mysql-mmm/ status_path /var/lib/misc/mmm_mond.status ping_ips 192.168.10.81,192.168.10.82,192.168.10.83,192.168.10.84 </monitor> <host default> monitor_user mmm_monitor monitor_password monitor </host> <check default> check_period 5 trap_period 10 timeout 3 max_backlog 86400 </check> debug 0
12、在monitor服務器的 /etc/init.d/mysql-mmm-monitor的腳本文件的#!/bin/sh下面,加入如下內容
source /root/.bash_profile
13、將mysql-mmm-monitor添加成系統服務並設置爲自啓動
#chkconfig --add mysql-mmm-monitor
#chkconfigmysql-mmm-monitor on
14、啓動monitor服務器的mysql-mmm-monitor服務
15、在monitor服務器執行命令列出客戶端狀態,發現都是AWAITING狀態
16、在monitor服務器執行命令mmm_control set_online mysql-master01,將mysql-master01上線,過一會再看它就變成online狀態了
17、這時觀察mysql-master01的IP發現已經成功添加了Write VIP
18、依次將mysql-master02和mysql-slave01以及mysql-slave02設置爲online,查看slave的IP也發現Read VIP也加上了。MMM到此已配置完成,下面將進行高可用測試
七、MySQL-MMM主庫高可用測試
1、將mysql-master01的mysql服務停止,模擬主庫宕機,再查看IP會發現Write VIP已被自動移除
2、觀察monitor服務器上的日誌可以發現MMM檢測到mysql-maste01故障並將Write VIP切換到了mysql-master02上
3、查看mysql-master02的IP,發現Write VIP確實已添加上了
4、這時兩臺slave之前配置的主庫已經宕機並且主庫已切換,那它們是否會自動將Master Host也切換爲mysql-master02呢?查看下它們的slave狀態,發現已自動切換
5、在monitor服務器上查看下客戶端的狀態,mysql-master01確實已離線,並且是能Ping通而mysql連接失敗
6、再次啓動master01的mysql服務,並設置爲online,可以看到Write VIP並不會回切(除非當前的主庫再次宕機)
7、觀察到monitor服務器的日誌如下:
8、再檢查下客戶端,已恢復正常
八、MySQL-MMM從庫高可用測試
1、將mysql-slave01的mysql服務停止,模擬從庫宕機,再查看IP會發現其上的Read VIP已被自動移除
2、觀察到monitor服務器上的日誌發現mysql-slave01的Read VIP已被切換到mysql-slave02上:
3、在monitor服務器上查看客戶端狀態,發現mysql-slave02確實綁定了2個Read VIP
4、檢查mysql-slave02的IP,確實如此
5、將mysql-slave01的mysql服務恢復啓動,並在monitor服務器將其設置爲online,可以看到切換回去的Read VIP並不是最開始的那個VIP,Read VIP並非固定不變
6、觀察monitor服務器的日誌內容如下:
7、兩個slave的IP信息現在如下:
至此,MySQL-MMM讀寫分離的高可用架構經簡單測試均OK!以下是小結:
1、若master01主節點宕機,由master02備選主節點接管寫角色,slave1,slave2指向新master2主庫進行復制,slave01,slave02會自動change master到master02。
2、若master01主節點宕機,而master02同步又落後於master01時就變成了主可寫狀態,則這時的數據主無法保證一致性。
3、若master02,slave01,slave02延遲於master01主,而這個時master01宕機,slave01,slave02將會等待數據追上master01後,再重新指向新的主master02進行復制操作,這時的數據也無法保證同步的一致性。
4、對外提供讀寫的虛擬IP是由monitor程序控制。如果monitor沒有啓動那麼db服務器不會被分配虛擬ip,但是如果已經分配好了虛擬ip,當monitor程序關閉了,則原先分配的虛擬ip不會關閉,只要不重啓網絡,外部程序還可以連接訪問,這樣能對monitor的可靠性要求降低一些,但是如果這時其中的某一個db服務器故障了就無法處理切換。因爲agent程序受monitor程序的控制,處理主庫切換、從庫切換等操作。如果monitor進程關閉了那麼agent進程就起不到什麼作用,它本身不能處理故障。
5、monitor程序負責監控db服務器的狀態,包括Mysql數據庫、服務器是否運行、複製線程是否正常、主從延時等,以及控制agent程序處理故障。因此monitor是這個高可用架構中的核心角色,同時也是單點故障的風險點,應該能通過keepalived等方式將monitor也做成高可用,等以後有時間我再進行測試。
6、monitor監控端的配置文件參數“auto_set_online”可以讓從故障中恢復的節點自動online,待有空測試下。羣集中節點服務器的狀態有三種分別是:HARD_OFFLINE→AWAITING_RECOVERY→online
7、默認monitor會控制mmm_agent會將writer db服務器read_only修改爲OFF,其它的db服務器read_only修改爲ON,所以爲了嚴謹可以在所有的服務器的my.cnf文件中加入read_only=1,由monitor控制writer和read,root用戶和複製用戶不受read_only參數的影響。
本文出自江健龍的技術博客,轉載請註明出處 http://blog.51cto.com/jiangjianlong/2073744