標籤:
一、複製的常用拓撲結構
複製的體繫結構有以下一些基本原則:
(1) 每個slave只能有一個master;
(2) 每個slave只能有一個唯一的伺服器ID;
(3) 每個master可以有很多slave;
(4) 如果你設定log_slave_updates,slave可以是其它slave的master,從而擴散master的更新。
MySQL不支援多主伺服器複製(Multimaster Replication)——即一個slave可以有多個master。但是,通過一些簡單的組合,我們卻可以建立靈活而強大的複製體繫結構。
1.1 單一master和多slave
在實際應用情境中,MySQL複製90%以上都是一個Master複製到一個或者多個Slave的架構模式,主要用於讀壓力比較大的應用的資料庫端廉價擴充解決方案。因為只要Master和Slave的壓力不是太大(尤其是Slave端壓力)的話,非同步複製的延時一般都很少很少。尤其是自從Slave端的複製方式改成兩個線程處理之後,更是減小了Slave端的延時問題。
當slave增加到一定數量時,slave對master的負載以及網路頻寬都會成為一個嚴重的問題
這種結構雖然簡單,但是,它卻非常靈活,足夠滿足大多數應用需求。一些建議:
(1) 不同的slave扮演不同的作用(例如使用不同的索引,或者不同的儲存引擎);
(2) 用一個slave作為備用master,只進行複製;
(3) 用一個遠端slave,用於災難恢複;
1.2 主動模式的Master-Master
這樣搭建複製環境之後,難道不會造成兩台MySQL之間的迴圈複製嗎?實際上MySQL自己早就想到了這一點,所以在MySQL的BinaryLog中記錄了當前MySQL的server-id,而且這個參數也是我們搭建MySQLReplication的時候必須明確指定,而且Master和Slave的server-id參數值比需要不一致才能使MySQLReplication搭建成功。一旦有了server-id的值之後,MySQL就很容易判斷某個變更是從哪一個MySQLServer最初產生的,所以就很容易避免出現迴圈複製的情況。
主動的Master-Master複製有一些特殊的用處。例如,地理上分布的兩個部分都需要自己的可寫的資料副本。這種結構最大的問題就是更新衝突。假設一個表只有一行(一列)的資料,其值為1,如果兩個伺服器分別同時執行如下語句:
在第一個伺服器上執行:
mysql> UPDATE tbl SET col=col + 1;
在第二個伺服器上執行:
mysql> UPDATE tbl SET col=col * 2;
那麼結果是多少呢?一台伺服器是4,另一個伺服器是3,但是,這並不會產生錯誤。
實際上,MySQL並不支援其它一些DBMS支援的多主伺服器複製(Multimaster Replication),這是MySQL的複製功能很大的一個限制(多主伺服器的痛點在於解決更新衝突),但是,如果你實在有這種需求,你可以採用MySQL Cluster,以及將Cluster和Replication結合起來,可以建立強大的高效能的資料庫平台。但是,可以通過其它一些方式來類比這種多主伺服器的複製。
1.3 主動-被動模式的Master-Master這是master-master結構變化而來的,它避免了M-M的缺點,實際上,這是一種具有容錯和高可用性的系統。它的不同點在於其中一個服務只能進行唯讀操作
1.4 級聯複製架構 Master –Slaves -Slaves
在有些應用情境中,可能讀寫壓力差別比較大,讀壓力特別的大,一個Master可能需要上10台甚至更多的Slave才能夠支撐注讀的壓力。這時候,Master就會比較吃力了,因為僅僅連上來的SlaveIO線程就比較多了,這樣寫的壓力稍微大一點的時候,Master端因為複製就會消耗較多的資源,很容易造成複製的延時。
遇到這種情況如何解決呢?這時候我們就可以利用MySQL可以在Slave端記錄複製所產生變更的BinaryLog資訊的功能,也就是開啟—log-slave-update選項。然後,通過二級(或者是更多層級)複製來減少Master端因為複製所帶來的壓力。也就是說,我們首先通過少數幾台MySQL從Master來進行複製,這幾台機器我們姑且稱之為第一級Slave叢集,然後其他的Slave再從第一級Slave叢集來進行複製。從第一級Slave進行複製的Slave,我稱之為第二級Slave叢集。如果有需要,我們可以繼續往下增加更多層次的複製。這樣,我們很容易就控制了每一台MySQL上面所附屬Slave的數量。這種架構我稱之為Master-Slaves-Slaves架構
這種多層級聯複製的架構,很容易就解決了Master端因為附屬Slave太多而成為瓶頸的風險,當然,如果條件允許,我更傾向於建議大家通過拆分成多個Replication叢集來解決
上述瓶頸問題。畢竟Slave並沒有減少寫的量,所有Slave實際上仍然還是應用了所有的資料變更操作,沒有減少任何寫IO。相反,Slave越多,整個叢集的寫IO總量也就會越多,我們沒有非常明顯的感覺,僅僅只是因為分散到了多台機器上面,所以不是很容易表現出來。
此外,增加複製的級聯層次,同一個變更傳到最底層的Slave所需要經過的MySQL也會更多,同樣可能造成延時較長的風險。
而如果我們通過分拆叢集的方式來解決的話,可能就會要好很多了,分拆叢集也需要更複雜的技術和更複雜的應用系統架構。
1.5 帶從伺服器的Master-Master結構(Master-Master with Slaves)這種結構的優點就是提供了冗餘。在地理上分布的複製結構,它不存在單一節點故障問題,而且還可以將讀密集型的請求放到slave上。
級聯複製在一定程度上面確實解決了Master因為所附屬的Slave過多而成為瓶頸的問題,但是他並不能解決人工維護和出現異常需要切換後可能存在重新搭建Replication的問題。這樣就很自然的引申出了DualMaster與級聯複製結合的Replication架構,我稱之為Master-Master-Slaves架構
和Master-Slaves-Slaves架構相比,區別僅僅只是將第一級Slave叢集換成了一台單獨的Master,作為備用Master,然後再從這個備用的Master進行複製到一個Slave叢集。
這種DualMaster與級聯複製結合的架構,最大的好處就是既可以避免主Master的寫入操作不會受到Slave叢集的複製所帶來的影響,同時主Master需要切換的時候也基本上不會出現重搭Replication的情況。但是,這個架構也有一個弊端,那就是備用的Master有可能成為瓶頸,因為如果後面的Slave叢集比較大的話,備用Master可能會因為過多的SlaveIO線程請求而成為瓶頸。當然,該備用Master不提供任何的讀服務的時候,瓶頸出現的可能性並不是特別高,如果出現瓶頸,也可以在備用Master後面再次進行級聯複製,架設多層Slave叢集。當然,級聯複製的層級越多,Slave叢集可能出現的資料延時也會更為明顯,所以考慮使用多層級聯複製之前,也需要評估資料延時對應用系統的影響。
二、mysql主從複製
主從複製的原理
分為同步複製和非同步複製,實際複製架構中大部分為非同步複製。 複製的基本過程如下:
1).Slave上面的IO進程串連上Master,並請求從指定記錄檔的指定位置(或者從最開始的日誌)之後的日誌內容;
2).Master接收到來自Slave的IO進程的請求後,通過負責複製的IO進程根據請求資訊讀取制定日誌指定位置之後的日誌資訊,返回給Slave 的IO進程。返回資訊中除了日誌所包含的資訊之外,還包括本次返回的資訊已經到Master端的bin-log檔案的名稱以及bin-log的位置;
3).Slave的IO進程接收到資訊後,將接收到的日誌內容依次添加到Slave端的relay-log檔案的最末端,並將讀取到的Master端的 bin-log的檔案名稱和位置記錄到master-info檔案中,以便在下一次讀取的時候能夠清楚的告訴Master“我需要從某個bin-log的哪個位置開始往後的日誌內容,請發給我”;
4).Slave的Sql進程檢測到relay-log中新增加了內容後,會馬上解析relay-log的內容成為在Master端真實執行時候的那些可執行檔內容,然後回放。
安裝配置
主伺服器master:192.168.1.30
從伺服器slave:192.168.1.25
master配置
my.cnf
#bin_logbinlog_format=mixedmax_binlog_size=200Mlog_bin=/data/logs/mysql/binarylog/mysql_binexpire_logs_days=7binlog-ignore-db = mysql,information_schema,performance_schemaserver_id=1binlog-do-db=abc
授權
GRANT REPLICATION SLAVE ON abc.* to ‘sync‘@‘192.168.1.30‘ identified by ‘123456‘
slave配置
server-id=131 #從伺服器ID號,不要和主ID相同master-host=192.168.1.30 #指定主伺服器IP地址master-user=sync #指定在主伺服器上可以進行同步的使用者名稱master-password=123456 #密碼master-port=3306 # 同步所用連接埠master-connect-retry=60 #斷點從新連線時間replicate-ignore-db=information_schema,mysql,performance_schema #屏蔽對mysql庫的同步replicate-do-db=abc #同步的資料庫的名稱replicate_do_table = tt #同步的資料表的名稱
授權
change master to master_host=‘192.168.1.30‘,master_port=3306,master_user=‘sync‘,master_password=‘123456‘,master_log_file=‘mysql_bin.000041‘,master_log_pos=538;
啟動slave
mysql> start slave;mysql> show slave status\G*************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.1.30 Master_User: sync Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql_bin.000042 Read_Master_Log_Pos: 120 Relay_Log_File: mysql-relay-bin.000004 Relay_Log_Pos: 283 Relay_Master_Log_File: mysql_bin.000042 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 120 Relay_Log_Space: 710 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1 Master_UUID: 7789d104-20d3-11e5-a394-0050563accdf Master_Info_File: /data/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 01 row in set (0.00 sec)
mysql replication單表或多表複製時需注意的幾個問題
1.主庫和從庫的資料庫名必須相同;
2.主庫和從庫的複製可以精確到表,但是在需要更改主庫或從庫的資料結構時需要立刻重啟slave;
3.不能在mysql設定檔裡直接寫入master的配置資訊,需要用change master命令來完成;
4.指定replicate_do_db必須在my.cnf裡配置,不能用change master命令來完成;
5.如果不及時清理,日積月累二進位記錄檔可能會把磁碟空間佔滿,可以在設定檔裡加上expire_logs_days=7,只保留最近7天的日誌,建議當slave不再使用時,通過reset slave來取消relaylog;
最後,編寫一shell指令碼,用nagios監控slave的兩個“yes”,如發現只有一個或零個“yes”,就表明主從有問題了,發警示簡訊
三、MySQL-MMM工作原理
MMM(Master-Master replication managerfor Mysql,Mysql主主複製管理器)是一套靈活的指令碼程式,基於perl實現,用來對mysql replication進行監控和故障遷移,並能管理mysql Master-Master複製的配置(同一時間只有一個節點是可寫的)。
mmm_mond:監控進程,負責所有的監控工作,決定和處理所有節點角色活動。此指令碼需要在監管機上運行
mmm_agentd:運行在每個mysql伺服器上的代理進程,完成監控的探針工作和執行簡單的遠端服務設定。此指令碼需要在被監管機上運行
mmm_control:一個簡單的指令碼,提供管理mmm_mond進程的命令
mysql-mmm的監管端會提供多個虛擬IP(VIP),包括一個可寫VIP,多個可讀VIP,通過監管的管理,這些IP會綁定在可用mysql之上,當某一台mysql宕機時,監管會將VIP遷移至其他mysql。
在整個監管過程中,需要在mysql中添加相關授權使用者,以便讓mysql可以支援監理機的維護。授權的使用者包括一個mmm_monitor使用者和一個mmm_agent使用者,如果想使用mmm的備份工具則還要添加一個mmm_tools使用者。
優缺點
資料庫分配
monitor192.168.1.29master-1192.168.1.25master-2192.168.1.26slave 1192.168.1.27slave 2192.168.1.28VIPwriter192.168.0.31reader192.168.0.32reader192.168.0.33
統一授權
GRANT REPLICATION SLAVE ON *.* TO ‘replication‘@‘192.168.1.%‘ IDENTIFIED BY ‘replication‘;
master-1配置192.168.1.25
[mysqld]#bin_logbinlog_format=mixedmax_binlog_size=200Mlog_bin=/data/logs/mysql/binarylog/mysql_binexpire_logs_days=0log_slave_updates #當一個主故障,另一個立即接管sync-binlog=1 #每條自動更新,安全性高,預設是0#relay_logrelay_log = mysql-relay-bin#replicateserver_id=1binlog-do-db=abc #需要記錄二進位日誌的資料庫,多個用逗號隔開binlog-ignore-db=mysql,information_schema,performance_schema #不需要記錄二進位日誌的資料庫,多個用逗號隔開auto_increment_increment=1 #欄位一次遞增多少auto_increment_offset=1 #自增欄位的起始值,值設定不同replicate-do-db=abc #同步的資料庫,多個寫多行replicate-ignore-db = information_schema #不同步的資料庫,多個寫多行replicate-ignore-db = mysql #不同步的資料庫,多個寫多行
授權
change master tomaster_host=‘192.168.1.26‘,master_user=‘replication‘,master_password=‘replication‘,master_log_file=‘mysql-bin.000006‘,master_log_pos=120;
master-2配置192.168.1.26
[mysqld]#bin_logbinlog_format=mixedmax_binlog_size=200Mlog_bin=/data/logs/mysql/binarylog/mysql_binexpire_logs_days=0log_slave_updates #當一個主故障,另一個立即接管sync-binlog=1 #每條自動更新,安全性高,預設是0#relay_logrelay_log = mysql-relay-bin#replicateserver_id=2binlog-do-db=abc #需要記錄二進位日誌的資料庫,多個用逗號隔開binlog-ignore-db=mysql,information_schema,performance_schema #不需要記錄二進位日誌的資料庫,多個用逗號隔開auto_increment_increment=1 #欄位一次遞增多少auto_increment_offset=1 #自增欄位的起始值,值設定不同replicate-do-db=abc #同步的資料庫,多個寫多行replicate-ignore-db = information_schema #不同步的資料庫,多個寫多行replicate-ignore-db = mysql #不同步的資料庫,多個寫多行
授權
change master tomaster_host=‘192.168.1.25‘,master_user=‘replication‘,master_password=‘replication‘,master_log_file=‘mysql-bin.000009‘,master_log_pos=220;
可能會出現的問題
1、Slave_IO_Running = NO ,Slave I/O: Got fatal error 1236 from master when reading data from binary log: ‘Could not find first log file name in binary log index file‘, Error_code: 1236
2、Slave_SQL_Running=NO ,Error ‘Can‘t create database ‘abc‘; database exists‘ on query. Default database: ‘abc‘. Query: ‘create database abc‘
3、授權失敗
主主同步配置完畢,查看同步狀態Slave_IO和Slave_SQL是YES說明主主同步成功
slave-1和slave-2做為master-1的從庫
change master tomaster_host=‘192.168.1.25‘,master_user=‘replication‘,master_password=‘replication‘,master_log_file=‘mysql-bin.000002‘,master_log_pos=434;
在slave1和slave2查看如下說明主從複製成功。但是資料沒過來,這是因為主從複製原理只同步配置完後的增刪改記錄,以前的資料是不能同步的,我們可以把主的Database Backup了,然後再還原
mysql> show slave status \G*************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.1.25 Master_User: replication Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql_bin.000009 Read_Master_Log_Pos: 410 Relay_Log_File: mysql-relay-bin.000012 Relay_Log_Pos: 283 Relay_Master_Log_File: mysql_bin.000009 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: abc Replicate_Ignore_DB: information_schema,mysql Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 410 Relay_Log_Space: 725 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 2 Master_UUID: fc4e74ed-563f-11e5-bff1-000c29ee3b5c Master_Info_File: /data/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0
MySQL-MMM安裝配置
CentOS 預設沒有 mysql-mmm 軟體包,官方推薦使用 epel 的網路源,五台都安裝epel:
rpm -ivh http://mirrors.ustc.edu.cn/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
monitor節點安裝
yum -y install mysql-mmm-monitor
db節點安裝
yum -y install mysql-mmm-agent
db節點授權monitor訪問
GRANT REPLICATIONCLIENT ON *.* TO ‘mmm_monitor‘@‘192.168.1.%‘ IDENTIFIED BY ‘123456‘;GRANT SUPER,REPLICATION CLIENT, PROCESS ON *.* TO ‘mmm_agent‘@‘192.168.1.%‘ IDENTIFIED BY ‘123456‘;
mmm_common.conf檔案(五台相同)
active_master_role writer<host default> cluster_interface eth0 pid_path /var/run/mysql-mmm/mmm_agentd.pid bin_path /usr/libexec/mysql-mmm/ replication_user replication replication_password replication agent_user mmm_agent agent_password agent</host><host db1> ip 192.168.1.25 mode master peer db2</host><host db2> ip 192.168.0.26 mode master peer db1</host><host db3> ip 192.168.0.27 mode slave</host><host db4> ip 192.168.0.28 mode slave</host><role writer> hosts db1, db2 ips 192.168.1.31 mode exclusive #只有一個host可以writer</role><role reader> hosts db3, db4 ips 192.168.1.32,192.168.1.33 mode balanced #多個host可以reader</role>
db端 mmm_agent.conf
include mmm_common.confthis db1 #分別修改為原生主機名稱,即db1、db2、db3和db4
管理端mmm_mon.conf檔案
include mmm_common.conf<monitor> ip 127.0.0.1 pid_path /var/run/mysql-mmm/mmm_mond.pid bin_path /usr/libexec/mysql-mmm status_path /var/lib/mysql-mmm/mmm_mond.status ping_ips 192.168.1.25,192.168.1.26,192.168.1.27,192.168.0.28#真實資料庫IP,來檢測網路是否正常 auto_set_online 10 #恢複後自動化佈建線上的時間</monitor><host default> monitor_user mmm_monitor monitor_password monitor</host>debug 0
啟動MySQL-MMM
db代理端啟動
/etc/init.d/mysql-mmm-agent startchkconfigmysql-mmm-agent on
monitor管理端啟動
/etc/init.d/mysql-mmm-monitor startchkconfigmysql-mmm-monitor on
查看叢集狀態
[[email protected] ~]# mmm_control show
參考文章
《MMM 之 MySQL》
《從零開始配置 MySQL MMM》
【mysql】高可用叢集之MMM