1.實現目標
?目標清單:
??? 1)Master(192.168.31.230)為正常運行環境下的主庫,為兩個Slave(192.168.31.231和192.168.31.232)提供“主-從”復制功能;
??? 2)Master_Backup(192.168.31.233)是Master的備份庫,只要Master是正常的,它不對外提供服務。它與Master之間屬于"主-主"復制關系,即自己既是主機,又是對方的從機;
??? 3)同理,192.168.31.234和192.168.31.235為Slave_Backup,分別為192.168.31.231和 192.168.31.232的備份庫,只要Slave是正常的,對應的備份機不對外提供服務;
??? 4)Slave在此架構中的目的是為了實現讀寫分離,對應用程序來說,Master只負責寫,兩個Slave只負責讀。Slave的數據來源于Master的復制操作;
??? 5)如果Master由于某種原因(例如:宕機和斷電等)導致不能正常運行,則此時需要讓Master_Backup自動切換為新主機,而Slave和Slave_Backup也能自動切換數據源到Master_Backup;
??? 6)同理,如果Slave由于某種原因(例如:宕機和斷電等)導致不能正常運行,則此時需要讓對應的Slave_Backup自動切換為新從機;
??? 7)無論是Master還是切換后的Master_Backup,它們向客戶端提供的連接地址應保持一致,如上圖提供的VIP+Port,即192.168.31.201:3306,Slave和Slave_Backup也應如此,對外提供的連接地址始終是192.168.31.202:3306和192.168.31.203:3306。
?2.實現過程
???? MySQL安裝步驟不在此講述。
2.1實現Master-Master結構
2.1.1修改Master和Master_Backup配置文件,vi /etc/my.cnf
??? 主要在[mysqld]內添加如下配置項:
Sql配置代碼 ?
#?log文件名,必填??log-bin?=?mysql-bin??#?服務器Id,必須唯一??server-id?=?230?? #?不參與同步的數據庫名,有多個則添加多個配置項??binlog-ignore-db?=?mysql??#?Master-Master結構必須的??log-slave-updates??slave-skip-errors?=?all??sync_binlog?=?1?? read_only?=?0?? 2.1.2為復制請求方提供鏈接賬號和密碼
??? 由于是Master-Master結構,因此需在雙方終端中執行如下SQL命令:
Sql代碼 ?
GRANT?REPLICATION?SLAVE?ON?*.*?to?'slave'@'%'?identified?by?'slave123';?? ??? 可在mysql實例的user表中查詢到記錄,重點關注Repl_slave_priv字段的值是否為Y,此賬號(用戶名:slave,密碼:slave123)主要用于定位復制點
2.1.3在從機上指定Master數據源
?? 1)在Master上執行
Sql代碼 ?
SHOW?MASTER?STATUS;??? ??? 得到的結果如下:
??? 重點關注File和Position兩個字段值
??? 2)在Master_Backup也執行上述步驟,由于是初始狀態,得到的結果和上圖一樣;
??? 3)在Master上執行如下SQL命令,填入Master_Backup的host、鏈接賬號和密碼、File和Position值
Sql代碼 ?
SLAVE?STOP;??CHANGE?MASTER?TO?MASTER_HOST='192.168.31.233',MASTER_USER='slave',MASTER_PASSWORD='slave123',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=107;?? SLAVE?START;?? ??? 4)在Master_Backup上執行如下SQL命令,填入Master的host、鏈接賬號和密碼、File和Position值 Sql代碼 ?
SLAVE?STOP;??CHANGE?MASTER?TO?MASTER_HOST='192.168.31.230',MASTER_USER='slave',MASTER_PASSWORD='slave123',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=107;?? SLAVE?START;?? ?? 5)重啟Master和Master_Backup
2.1.4測試
??? 1)當Master和Master_Backup都正常運行時,在任意一端更新數據后都會同步到另一段;
??? 2)當Master處于不可運行時,在Master_Backup更新數據后重啟Master,這時在Master上可得到最新的數據;
??? 3)當Master_Backup處于不可運行時,在Maste更新數據后重啟Master_Backup,這時在Master_Backup上可得到最新的數據。
2.2實現Master-Slave結構
2.2.1實施過程
???? 將2.1.1和2.1.3的過程在所有Slave上操作一遍即可,需要注意配置文件中server-id一定要唯一,還有在執行CHANGE MASTER TO命令時,MASTER_HOST為192.168.31.230
Sql代碼 ?
SLAVE?STOP;??CHANGE?MASTER?TO?MASTER_HOST='192.168.31.230',MASTER_USER='slave',MASTER_PASSWORD='slave123',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=107;?? SLAVE?START;?? ?2.2.2測試
??? 1)當Master和Master_Backup都正常運行時,在任意一端更新數據后都會同步到兩個Slave上;
??? 2)當Master處于正常運行時,在此端更新數據后都會同步到兩個Slave上,而無論Master_Backup是否正常;
??? 3)當Master處于不可運行時,Master_Backup通過Monitor(Keepalived)成為接管者,在Master_Backup更新數據后都會同步到所有Slave上,并且重啟Master后,最新數據也會同步到此端。
??? 可事與愿違,在第3)種場景下,Master_Backup不會將數據同步給Slave,即使后來在Slave上將MASTER_HOST指定為Keepalived提供的VIP(192.168.31.201)也無濟于事:
Sql代碼 ?
SLAVE?STOP;??CHANGE?MASTER?TO?MASTER_HOST='192.168.31.201',MASTER_USER='slave',MASTER_PASSWORD='slave123',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=107;?? SLAVE?START;?? ??? 在Slave上執行SHOW SLAVE STATUS;
??? 得出如下結果:
???? 究其原因,如上圖所示,Master_Server_Id為230,仍然指向的是已經處于不可運行的Master,而預期結果是希望它能自動的更新定位到Master_Backup(233)上,達到自動切換的目的。
???? 沒辦法,只有自己執行CHANGE MASTER TO...手動定位了。我草...,一不注意就會定位錯誤,造成數據丟失的問題,而且也不滿足快速響應容災切換的目的。
3.最終方案
??? 最終方案將選擇mysql-mmm結合半同步機制來實現容災自動切換。
3.1在master(230和233)上安裝semisync master并設置
Sql代碼 ?
INSTALL?PLUGIN?rpl_semi_sync_master?SONAME?'semisync_master.so';?? INSTALL?PLUGIN?rpl_semi_sync_slave?SONAME?'semisync_slave.so';?? SET?GLOBAL?rpl_semi_sync_master_enabled?=?1;??SET?GLOBAL?rpl_semi_sync_slave_enabled?=?1;?? ?vi /ect/my.cnf后加入如下配置:
配置代碼 ?
rpl_semi_sync_master_enabled?=?1?? rpl_semi_sync_slave_enabled?=?1?? 3.2在slave(231、232、234和235)上安裝slave插件并設置
Sql代碼 ?
INSTALL?PLUGIN?rpl_semi_sync_slave?SONAME?'semisync_slave.so';?? SET?GLOBAL?rpl_semi_sync_slave_enabled?=?1;?? ?vi /ect/my.cnf后加入如下配置:
配置代碼 ?
rpl_semi_sync_slave_enabled?=?1?? 3.3所有mysql實例停止slave并開啟slave,使半同步機制生效
Sql代碼 ?
stop?slave;??start?slave;?? 3.4查看semisync狀態
Sql代碼 ?
show?status?like?'%emi%';?? ?重點關注:
1)Rpl_semi_sync_master_clients:與當前master建立半同步連接的客戶端數;
2)Rpl_semi_sync_master_status:作為半同步master端的就緒狀態(ON:就緒,OFF:未就緒)
3)Rpl_semi_sync_slave_status:作為半同步slave端的就緒狀態(ON:就緒,OFF:未就緒)
3.5安裝mysql-mmm
3.5.1新增一臺專門用于監控mysql的服務器(mysql_monitor),IP為192.168.31.250
3.5.2在mysql_monitor、master、master_backup、slave和slave_backup上安裝epel網絡源
Linux命令行代碼 ?
yum?install?http://mirrors.hustunique.com/epel//6/x86_64/epel-release-6-8.noarch.rpm?? 3.5.3在mysql_monitor上安裝mysql-mmm-monitor
Linux命令行代碼 ?
yum?-y?install?mysql-mmm-monitor?? 3.5.4在master、master_backup、slave和slave_backup上安裝和配置
1)安裝mysql-mmm-agent
Linux命令行代碼 ?
yum?-y?install?mysql-mmm-agent?? ?2)授權monitor訪問
Sql代碼 ?
GRANT?REPLICATION?CLIENT?ON?*.*?TO?'mmm_monitor'@'192.168.31.%'?IDENTIFIED?BY?'monitor';???????GRANT?SUPER,REPLICATION?CLIENT,?PROCESS?ON?*.*?TO?'mmm_agent'@'192.168.31.%'?IDENTIFIED?BY'agent';?? 3)編輯mmm_agent.conf配置文件
vi /etc/mysql-mmm/mmm_agent.conf
Mmm_agent.conf配置文件代碼 ?
#?包含公用配置文件??include?mmm_common.conf???#?對應<code><span?style="color:?#008000;"><span?style="color:?#000000;">mmm_common.conf中定義的某個host名稱</span></span></code>?? this?db1??#?設置成1時,將打印日志到前臺,按ctrl+c將結束進程?? debug?0?? max_kill_retries?1?? 4)編輯mmm_common.conf配置文件
vi /etc/mysql-mmm/mmm_common.conf
Mmm_common.conf代碼 ?
active_master_role??????writer????<host?default>??????#?對應當前主機的網絡接口名??????cluster_interface???????eth2??????pid_path????????????????/var/run/mysql-mmm/mmm_agentd.pid??????bin_path????????????????/usr/libexec/mysql-mmm/??????mysql_port??????????????3306?? ????agent_port??????????????9989?? ????#?對應GRANT?REPLICATION?SLAVE?ON語句創建的賬號和密碼??????replication_user????????slave??????replication_password????slave123??????#?GRANT?SUPER,REPLICATION?CLIENT,?PROCESS?ON語句創建的賬號和密碼??????agent_user??????????????mmm_agent??????agent_password??????????agent??</host>????#?master的配置??#?其中host后面的值定義的是某臺數據庫服務的別名,一般就用服務器的主機名即可??<host?db1>??????ip??????192.168.31.230?? ????mode????master??????#?db1的master對等點??????peer????db2??</host>????#?master_backup的配置??<host?db2>??????ip??????192.168.31.233?? ????mode????master???????#?db2的master對等點??????peer????db1??</host>????#?slave的配置??<host?db3>???????ip?????192.168.31.231?? ?????mode???slave??</host>????#?slave的配置??<host?db4>???????ip?????192.168.31.232?? ?????mode???slave??</host>????#?slave_backup的配置??<host?db5>???????ip?????192.168.31.234?? ?????mode???slave??</host>????#?slave_backup的配置??<host?db6>???????ip?????192.168.31.235?? ?????mode???slave??</host>????#?定義writer角色,即架構中的master和master_backup??#?ips為writer對外提供的vip??<role?writer>??????hosts???db1,?db2??????ips?????192.168.31.201?? ????mode????exclusive??</role>????#?定義reader角色,即架構中的兩個slave和兩個slave_backup??#?ips為reader對外提供的vip??<role?reader>??????hosts????db3,?db4,?db5,?db6??????ips??????192.168.31.202,?192.168.31.203?? ????mode?????balanced??</role>?? ?注意,需要將此配置文件復制到mysql_monitor的同名目錄下
3.5.5在master、master_backup、slave和slave_backup上啟動mmm agent服務,并設置為開機服務
執行如下啟動命令:
Linux命令行代碼 ?
/etc/init.d/mysql-mmm-agent?start?? ?如果出現如下示例信息:
則說明配置成功
vi /etc/rc.d/rc.local后,將上述命令行添加到mysql啟動命令的下面
3.5.6編輯mysql_monitor上的配置文件mmm_mon.conf
vi /etc/mysql-mmm/mmm_mon.conf
Mmm-mon.conf代碼 ?
include?mmm_common.conf????<monitor>??????#?本機IP??????ip??????????????????192.168.31.250?? ????port????????????????9988?? ????pid_path????????????/var/run/mysql-mmm/mmm_mond.pid??????bin_path????????????/usr/libexec/mysql-mmm??????status_path?????????/var/lib/mysql-mmm/mmm_mond.status??????#?所有MySQL服務器的IP??????ping_ips????????????192.168.31.230,?192.168.31.231,?192.168.31.232,?192.168.31.233,?192.168.31.234,?192.168.31.235?? ????auto_set_online?????0?? </monitor>????<host?default>??????#?GRANT?REPLICATION?CLIENT?ON語句創建的賬號和密碼??????monitor_user????????mmm_monitor??????monitor_password????monitor??</host>????<check?mysql>??????#?每5秒檢查一次?? ????check_period????????5?? ????trap_period?????????10?? ????#?檢查超時秒數??????timeout?????????????2?? ????restart_after???????10000?? ????max_backlog?????????60?? </check>??<code>#?設置為1,開啟調試模式,打印日志到前臺,ctrl+c將結束進程,對于調試有幫助</code>?? debug?0?? ?????? 關于mmm_agent.conf、mmm_common.conf、mmm_mon.conf和
mmm_mon_log.conf的具體內容,可以參考http://blog.chinaunix.net/uid-16844903-id-3152138.html 3.5.7在上mysql_monitor開啟mmm monitor監控,并設置為開機服務
??? 執行如下啟動命令:
Linux命令行代碼 ?
/etc/init.d/mysql-mmm-monitor?start?? ??? 如果出現如下示例信息:
??? 則說明配置成功
vi /etc/rc.d/rc.local后,將上述命令行添加于此
3.5.8重啟所有服務器系統后測試
1)在mysql_monitor上執行如下命令,查看各監控機的運行狀態
Linux命令行代碼 ?
mmm_control?show?? ??? 得到如下示例結果:
???? 理想情況下,所有的MySQL都應該處于“ONLINE”狀態,這里的結果與第1節中的目標清單有一定誤差,因為202和203這個“讀”IP浮動到slave正好與預期結果相反,這和MySQL的啟動順序有關,而且最重要的是在mmm_common.conf中沒有作嚴格的控制,對于兩個slave(231和232)和兩個slave_backup(234和235)來說,得到202和203這兩個"讀"IP的機會是均等的。
???? 現在重新執行2.2.2節的測試場景3),停掉maste后稍等片刻,再執行mmm_control show得到如下結果:
???? 原來的master已處于不可用(HARD_OFFLINE)狀態,master_backup(233)成為了新的master,此時再在各slave和slave_backup上執行SHOW SLAVE STATUS;
???? 可以看出,不用再自己手動定位,就可以讓Master_Host和Master_Server_Id自動定位到當前處于“ONLINE”狀態的Master_Backup上。
??? 1)在Master_Backup上更新數據,在所有的slave和slave_backup上可以很快的查詢到最新的數據;
??? 2)重啟Master并稍等片刻后,在這臺主機上也可以查詢到最新的數據,此時writer權限仍在Master_Backup上。
4.最終架構
5.總結
?????? 接3.5.8測試場景2),雖然Master已恢復了“ONLINE”狀態,但整個架構是“非搶占式”的,writer權限仍在Master_Backup上,所以在Master上更新數據不會同步到其它主機上。因此,在實際使用過程中,除進行數據庫維護用真實IP訪問之外,其余操作都只使用VIP來進行,201為wirter,202和203為reader。
?????? 從第4節的架構圖中看出,Mmm_Mnitor存在單點問題,當Mmm_Mnitor處于不可運行時,整個主從結構將不能正常運行。可以部署多個監控,結合Keepalived來擴展。
?????? "主-主"和“主-從”架構通常有兩個目的:第一是為了進行容災備份,當數據庫發生不可預知的錯誤導致不可運行甚至丟失數據時,其余的備份機可以繼續對外提供數據讀寫服務。第二是為了分攤數據庫壓力實現"讀寫分離"。
?????? 讀寫分離會帶來數據延遲達到的問題。假設有一個業務,當數據插入到數據庫后要立即又從數據庫中將此數據查詢出來,因此當數據插入到Master庫后,由于網絡的延遲,Slave庫中不會立即得到這條最新的數據,此時應用程序查詢Slave庫將得不到預期結果。
?????? 通常有如下兩個方案解決上述問題:
?????? 1)將此類業務控制在一個數據庫事務中進行,讀寫都在master中進行。因此,在mmm_common.conf配置文件中,還需要將db1和db2同時配置在reader組:
Mmm_common.conf配置摘要代碼 ?
<role?writer>??????hosts???db1,?db4??????ips?????192.168.31.201?? ????mode????exclusive??</role>????<role?reader>??????hosts????db1,?db4,?db2,?db3,?db5,?db6???????ips??????192.168.31.202,?192.168.31.203?? ????mode?????balanced??</role>?? ??? 2)使用Zookeeper來解決分布式一致性問題,后續單獨再來介紹。
總結
以上是生活随笔為你收集整理的mysql两主多从的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。