一、MySQL簡單復制相關概念:
1. mysql復制的意義:Mysql復制是使得mysql完成高性能應用的前提
2. mysql復制的機制:
SLAVE端線程:
IO thread: 向主服務請求二進制日志中的事件
當讀取完畢后,IO線程將進行睡眠,當主服務器有新數據時,則主服務器喚醒從服務器的IO線程
SQL thread:從中繼日志讀取事件并在本地執行,
如果二進制日志開啟式,同樣會記錄二進制日志,但為了節約空間和提高性能,需要關閉
從服務器不能執行寫操作,如果執行寫操作則和主服務器不同步。
MASTER端:
binlog dump: 將IO thread請求的事件發送給對方;
默認為異步工作模式:主要主服務器自己寫完,不管從服務器是否寫完,就將返回
二、MySQL復制的常見構架
1. 主從構架
1)對于一從多主,只有新版本Mysql可以實現。 通常來說,一個從只能有一個主服務器,但是可以輪換。在某一時刻只能有一臺主服務器。
MariaDB-10:支持多主模型,多源復制(multi-source replication)
2)一主多從:執行寫操作只能對主服務器進行。 多從會增大主服務器壓力。
此時需要一個調度器,來分離讀寫請求到主從服務器上。所謂讀寫分離
3)讀寫分離:主從模型下,讓前端分發器能識別讀/寫,并且按需調度至目標主機;
amoeba,mysql-proxy可以實現讀寫分離調度
讀服務器進行負載均衡,使用一致性哈希算法,虛擬節點來分配訪問。
2.雙主構架
1) 使用server_id來避免循環賦值
2) 必須設定雙方的自動增長屬性,以避免沖突, 一個使用偶數一個實用技術
第一臺服務器:
auto_increment_increment=1 定義自動增長字段起始值
auto_increment_offset=2 步長
第二臺服務器
auto_increment_increment=2 定義自動增長字段起始值
auto_increment_offset=2 步長
通過以上設定來解決沖突問題。
3) 數據不一致; 在雙主模型下某些時刻會導致數據不同步。
第一個服務器鎖定第一個字段改第二個字段
第二臺服務器鎖定第二個字段改第一個字段
例如一個表包含: Age, Salary
如果一個人的年齡為31而工資2900,執行以下操作
A: update t1 set Salary=salary+1000 WHERE Age>=30;
B: update t1 set Age=Age-3 WHERE Salary < 3000;
會導致:
服務器A Salary 變為3900,年齡31
服務器B Salary 變為年齡28, 工資290
4) 功能:
不能分攤寫請求,兩個服務器寫壓力一致。
三、復制構架擴展
1. 主從服務器之間的差距
長時間運行后,主從可能不同步。 因為主服務器可以寫并發,但是從服務器的同步只能是但進程。
從服務器落后,有時候需要認為設計,來做備份。
2. 一主多從的環境:
1) 一主多從的環境中,為了利用各從服務器的緩存能力。需要一些負載均衡算法,來綁定特定查詢到特定服務器上,來使得緩存命中。這是這樣做使得均衡效果被打破,使得有的服務器過于繁忙。
2) 為了解決此問題,可以引入中心緩存服務器。
3) 由于換從服務器工作在旁路模式下,所以是否緩存取決于客戶端程序。
memcached:可以提供緩存能力+API
公共緩存服務器,性能比Mysql自身差
3. 多級復制: 主指向一個從,從同時也作為其他從服務器的主
master –> slave/master —> slave
中間服務器需要開啟二進制日志和中繼日志
多級復制可以降低主服務器產生mysqldump的壓力,把壓力分攤給下一集。 但是可能使得數據不能更好跟新。
可以把中間服務器的讀寫引擎改為black hole,來降低本地壓力,只生成二進制日志作為中繼服務器(relay server),然后把二進制日志發送給下游服務器
4. 模擬一從多主模型:
根據時間,來卻換不同的主。
通常用于在不同服務器之間做數據收集。
5. 環狀模型:
每臺服務器都是下一臺服務器的主服務器同時也是上一臺服務器的從服務器,使得每臺服務器都是主從,形成傳遞環。
每臺服務器的修改都會同步到環上任何一臺服務器中。
server_id 不能相同。
6. 常見mysql構架
1)一主一從,并且讀取分離
2)一主多從,主負責讀,從負責寫
3)一主多從外加一個冷備服務器, 只用于備份。 每一段時間關掉進行備份。
4)多主模型: 通過心跳信息探測主服務器的健康狀態,如果一個主掛掉,馬上切換另一個主
潛在問題: 第一臺服務器上未提交的事務,切換時將被回滾。
GTID(GLOBAL TRANSACTION id): 保證在特定服務器上的事務是完整的,如果執行不成功就回滾。
7.高級應用架構:
讀寫分離+負載均衡: 讀直到從服務器上面讀,寫只在主服務器上面寫。 需要在讀寫分離器之前加memocached
amoeba, mysql proxy
8. 異地同步: 主要避免自然災害
四、 簡單主從構架配置過程
1. 配置需留意
1)版本注意:主從版本一致,或者主版本高于從版本
2)從哪兒開始復制:
1. 都從0開始:
2. 主服務器已經運行一段時間,并且存在不小的數據集:
把主服務器備份,然后在從服務恢復,從主服務器上備份時所處的位置開始復制;
2. 配置過程:
主服務器:
1. 改server-id: 配置文件中寫入
vim /etc/my.cnf 在服務器段寫入 server_id=1 mysql> SHOW GLOBAL VARIABLES LIKE 'server_id'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | server_id | 1 | +---------------+-------+ 1 row in set (0.01 sec)
2. 啟用二進制日志
log_bin=/data/binlog/mysql-bin 同樣寫在配置文件的服務器段 mysql> SHOW GLOBAL VARIABLES LIKE 'log_bin%'; +---------------------------------+------------------------------+ | Variable_name | Value | +---------------------------------+------------------------------+ | log_bin | ON | | log_bin_basename | /data/binlog/mysql-bin | | log_bin_index | /data/binlog/mysql-bin.index |
3. 創建有復制權限的帳號
mysql> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'slaveUser'@'192.168.98.133' IDENTIFIED BY 'slaveuser' ; mysql> FLUSH PRIVILEGES ;
從服務器:
1. 改server-id, 寫在配置文件中
server_id=11
2. 啟用中繼日志,關閉二進制日志,寫入配置文件中
log_bin=OFF relay_log=/data/relay_log/relay_bin
3. 連接主服務器
命令: CHANGE MASTER TO MASTER_HOST = '', 主服務器地址 MASTER_USER='', 使用哪個用戶連接 MASTER_PASSWORD='', 密碼 MASTER_LOG_FILE='', 用來復制特定的哪一個二進制文件 MASTER_LOG_POS=;從這個二進制文件的哪個位置開始復制 最重要的參數只有前三個,就可以開始工作 mysql> CHANGE MASTER TO MASTER_HOST='192.168.98.129',MASTER_USER='slaveUser',MASTER_PASSWORD='slaveuser';
4. 啟動復制線程
mysql>START SLAVE; 這里其實可以單獨操作兩個線程,可以獨自控制1/O線程或者SQL線程開啟
# tail /var/log/mysql.log 2015-12-07 15:54:35 8511 [Note] Slave SQL thread initialized, starting replication in log 'FIRST' at position 0, relay log '/data/relay_log/relay_bin.000001' position: 4 mysql>SHOW SLAVE STATUS \G; 重點查看一下幾行 Master_Host: 192.168.98.129 Master_User: slaveUser Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 8443 Relay_Log_File: relay_bin.000002 Relay_Log_Pos: 8606 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Exec_Master_Log_Pos: 8443 Relay_Log_Space: 8773
簡單主從復制實驗過程的一些總結:
1)主服務器二進制日志如果在數據庫初始化的時候開啟了,則從服務器需要指定初始化結束后的日志進行復制。否則貌似會出現一些奇怪的錯誤。也許是因為無法再次創建系統庫所致
2)主服務器最好在系統庫初始化完成后再開啟二進制日志。 這樣從服務器就可以直接從第一個二進制日志開始復制。
3)如果錯誤日志中出現錯誤通常就是slave sql 線程,Slave I/O 產生的。 如果slave I/O出問題通常與權限和鏈接有關。 Slave sql出問題通常與二進制日志在從服務器執行有關。
3. 在主從架構中跟復制相關的文件:
1) master.info: 用于保存了從服務器連接到主服務器需要的信息。每一行有一個值。 不同的mysql版本格式不一樣。 如果不想鏈接,直接刪了就好了
2)relay-log.info: 二進制日志和中繼日志的位置, 日志坐標, 會不停的自動更新。由于更新不會馬上執行,會存在緩沖區,如果斷電,信息會丟失
為了復制安全性,需要在從服務器上,需要在從服務器上開啟一下參數。
sync_master_info =1 sync_relay_log =1 sync_relay_log_info =1
3)從服務器意外崩潰時,建議使用pt-slave-start命令來啟動slave;
4. 基于行和基于語句的復制:
1) 基于語句:
優點: 數據量小,易于查看和識別,適應性強
缺點: 有些語句無法精確復制,使用觸發器存儲過程等代碼的應用實現精確復制。
2)基于行復制:
優點: 都能精確完成復制,包括出發器存儲過程,能完成幾乎所有的復制功能, 較少占用CPU資源,可以減少鎖的使用
缺點: 通過日志無法判斷執行了哪些語句, 數據可能略大。
3)單獨使用基于語句的場景幾乎不存在,默認為混合模式。
5. 從服務器落后于主服務器如何檢測:
mysql> SHOW SLAVE STATUS \G; 可以查看 Seconds_Behind_Master: 0 這里顯示落后主服務器多少秒。 如果主服務器繁忙,這個值通常都為正值, 如果此值在波動而不是變大。都可以接受。
6. 評估主從服務器表數據是否一致:
procona-toolkit里面的一些工具可以進行監控
pt-table-checksum 在主服務器上面運行,可以自動尋找哪個表不同步
不同步的解決方法:
1.從新備份,并在從服務器上導入數據。
2.使用pt-table-sync完成同步
pt-summary 可以得到一些mysql的統計數據,有些時候有用
7. 為了提高復制時的數據安全性,在主服務器上的設定:
sync_binlog = 1 innodb_flush_log_at_trx_commit = 1 此參數的值設定為1,性能下降會較嚴重;因此,一般設定為2等,此時,主服務器崩潰依然有可能導致從服務器無法獲取到全部的二進制日志事件; 如果主服務器意外崩潰,有二進制日志中事件沒復制完損壞,可以在從服務器使用如下參數忽略: sql_slave_skip_counter = 0 數據目錄磁盤空間不足,也可導致復制無法進行。需要結合監控工具做整體評估。 主服務器修改過大,使得帶寬不夠用。
五、MySQL簡單復制應用擴展
1. 主從服務器需要保證時間同步,可以使用ntp服務
2. 如何限制從服務器制度
read_only=ON 定義在[mysqld]
注意: 對于不具有super權限的用戶有效,因此管理員依然有效,切勿使用管理員權限在從服務器上修改數據。
想限制所有用戶:
mysql> FLUSH TABLES WITH READ LOCK;
3. 如何主從復制時的事務安全
當主服務器事務,尚未同步到二進制日志中時, 如果主服務器宕機,則從服務器無法獲取完整的事務,當從服務器指向其它主服務器時候,有可能導致事務回滾。從而使得事務丟失。
在主服務器上配置一下參數解決, 只要事務提交,則立即將事務從二進制緩沖區同步到二進制日志中。
sync_binlog=1 innodb_flush_log_at_trx_commit=1
此變量設置后,會產生一些性能損耗,主要原因是MyISAM或者Innodb是默認自動提交事務的。為了提高性能可以關掉自動提交,同時開啟以上選項用。
全同步: 主服務器寫操作 –> 寫操作同步到二進制日志 –> 寫操作被復制到從服務器的二進制日志中 –> 才從服務器上執行寫操作 –> 然后返回給主服務器
4. 使用半同步復制(semi-synchronously)機制可以在主服務器性能一定損失的前提下實現更好地同步.
前面部分與全同步相同,只是在對于一主多從的場景中,主服務器只等待一個最快的從服務器范圍寫完成狀態。
半同步的配置: mysql5.5以后google提供,在lib/plugin目錄下的兩個插件semisync_master.so, semisync_slave.so。
主服務器配置: 裝載semisync_master.so模塊 mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; 裝載后,將會多出幾個選項 mysql> SHOW GLOBAL VARIABLES LIKE '%semi%'; +------------------------------------+-------+ | Variable_name | Value | +------------------------------------+-------+ | rpl_semi_sync_master_enabled | OFF | | rpl_semi_sync_master_timeout | 10000 | | rpl_semi_sync_master_trace_level | 32 | | rpl_semi_sync_master_wait_no_slave | ON | +------------------------------------+-------+ rpl_semi_sync_master_enabled : 控制是否開啟半同步 rpl_semi_sync_master_timeout : 半同步超時時長,多長時間半同步從服務器還為回復時,跳過半同步繼續執行。 單位為毫秒,默認為10秒鐘 rpl_semi_sync_master_wait_no_slave : 如果半同步服務器不回應,則跳過半同步服務器繼續執行。 修改修改前兩個參數: mysql> SET GLOBAL rpl_semi_sync_master_enabled='ON'; mysql> SET GLOBAL rpl_semi_sync_master_timeout=2000; 從服務器配置: 裝載semisync_master.so模塊 mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; 裝載后會出現以下參數 mysql> SHOW GLOBAL VARIABLES LIKE '%semi%'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | rpl_semi_sync_slave_enabled | OFF | | rpl_semi_sync_slave_trace_level | 32 | +---------------------------------+-------+ 從服務器這里只需要把第一個開啟就好: mysql> SET GLOBAL rpl_semi_sync_slave_enabled='ON'; mysql> STOP SLAVE IO_THREAD; mysql> START SLAVE IO_THREAD; 如果不重啟I/O 線程,則半同步從服務器特性不能被主服務器識別,此時主服務器上進行操作,會超時,然后跳過半同步。 查看狀態 mysql> SHOW GLOBAL STATUS LIKE '%semi_sync%'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 1 | 這里顯示,半同步客戶端有一個,說明半同步正常使用。 如果由于網絡或其他原因,檢測到半同步超時,則可以重啟從服務器的1/O線程,來重啟半同步功能。
5. 在主從復制架構中,僅復制一部分數據解決方案,使用復制過濾器實現
主服務器過濾: 主服務器僅往二進制日志中記錄像樣的服務器
優缺點:主服務器磁盤I/O 帶寬節約
缺點:但是其他數據庫數據不安全,無法完成時間點還原
參數:
binlog_do_db= binlog_igore_db=
在從服務器上,僅讀取相應的信息
基于庫
replicate_do_db= replicate_ignore_db=
基于表
replicate_do_table=db_name.tb_name replicate_ignore_table=
基于表使用通配符
replicate_wild_do_table= replicate_wild_ignore_table=
6. 配置多主模型
1) 兩臺服務器上各自建立一個具有復制權限的用戶;
主A: mysql> GRANT REPLICATION CLIENT,REPLICATION SLAVE ON *.* TO 'slaveUser'@'192.168.98.129' IDENTIFIED BY 'slaveuser'; mysql> FLUSH PRIVILEGES ; 主B: mysql> GRANT REPLICATION CLIENT,REPLICATION SLAVE ON *.* TO 'slaveUser'@'192.168.98.129' IDENTIFIED BY 'slaveuser'; mysql> FLUSH PRIVILEGES ;
2) 修改配置文件:
# 主服務器A上 [mysqld] server_id=1 log_bin=/data/binlog/mysql-bin relay-log=/data/relaylog/relay-bin auto-increment-offset=1## 起始位置 auto-increment-increment=2## 自動增長的步長 # 主服務器B上 [mysqld] server_id=11 relay_log=/data/relaylog/relay_bin log_bin=/data/binlog/mysql_bin auto-increment-offset=2## 起始位置 auto-increment-increment=2## 自動增長的步長
3) 相互作為從服務器指向對方
mysql> CHANGE MASTER TO MASTER_HOST='192.168.98.133',MASTER_USER='slaveUser',MASTER_PASSWORD='slaveuser',MASTER_LOG_FILE='mysql_bin.000002',MASTER_LOG_POS=120; mysql> CHANGE MASTER TO MASTER_HOST='192.168.98.129',MASTER_USER='slaveUser',MASTER_PASSWORD='slaveuser',MASTER_LOG_FILE='mysql-bin.000004',MASTER_LOG_POS=120; 此時就可以相互傳數據了: 這里有一個奇怪的現象: 如果兩個服務器一個一個插入數據,則可以總體順序按照1,2,3,4順序 如果一個服務器連續插入兩個以上,比如A連續插入兩個,B插入兩個, 則序號變為1,3,4,6。 也就是說不能在已插入位置之前插入序號。
多主模型和高可用解決方案
MMM: Multi Master Mysql
MHA: Mysql HA
7. 基于SSL進行通信
服務器端,驗證客戶端。
原創文章,作者:以馬內利,如若轉載,請注明出處:http://www.www58058.com/10024