天天看點

在ECS上自建MySQL手工容災環境

1.環境介紹

很多雲上的客戶因為資料庫規模小,可能最開始隻購買了ecs,而他們也需要資料庫伺服器,很可能會采用自建mysql來實作。阿裡雲rds已經提供了完全的資料庫運維服務,包括監控、優化、主備高可用等。而對小白使用者來說,為了自己業務連續性和學習的需要,也是很有必要了解如何自建mysql主備以及主備切換流程的。在主從複制實施前,單機單執行個體缺乏實時資料複制方案來保證執行個體出現故障時提供另一個完好且獨立的執行個體迅速切換,短時間内恢複客戶業務。

2.資料庫主從複制實施

2.1.主從複制原理

mysql提供簡單可靠的主從複制機制供使用者使用,基本原理如下圖所示,分三個步驟:

(1) master将改變記錄到二進制日志(binary log)中(這些記錄叫做二進制日志事件,binary log events);

(2) slave将master的binary log events拷貝到它的中繼日志(relay log);

(3) slave重做中繼日志中的事件,将改變反映它自己的資料。

在ECS上自建MySQL手工容災環境

2.2.主從複制規劃

mysql提供了主從複制元件,但是并不提供ha的自動監控切換。阿裡集團内部有自研工具可以實作ha功能,開源元件keepalived + lvs也提供類似功能。這裡我們提一個帶slb的方案,自動ha的實作留給讀者去研究。假設我們有2個mysql執行個體,一個執行個體為a,一個為b,我們考慮使用主從雙向複制,即mm(master-master)的方案進行部署,前端挂給slb,在同一個時刻,slb隻設定一個主用的執行個體權重為100,另一個備用執行個體權重為0,且将該執行個體的read_only參數打開。在發生故障時,将備用執行個體的權重設成100,主用執行個體設成0,這樣通過slb來實作手工的ha處理。對應用來說,将出現短時間(1-2分鐘)的不可用,當slb的切換完成後,應用通過連接配接池的重連機制,能重新恢複業務。

2.3.主從複制實施

(1) 生産執行個體在一個已經存在的ecs上已經準備好,申請一個新的ecs,保證該ecs不與生産執行個體的ecs在同一個實體機nc。如果生産執行個體的mysql是安裝在系統盤,可以從系統盤建立快照後打鏡像,新ecs依舊該自定義鏡像進行建立,這樣可以省略步驟

(2) 在新的ecs上安裝配置mysql,盡可能保證配置與生産執行個體完全一緻;

(3) 編輯生産執行個體的的/etc/my.cnf檔案,加入如下内容:

log-bin=/home/mysql/log/mysql-bin

server_id=1241823306

binlog_cache_size=32k

max_binlog_cache_size=2g

max_binlog_size=500m

binlog-format=row

sync_binlog=1

log-slave-updates=1

expire_logs_days=0

以上内容重點配置binlog,除server_id需要修改成ip位址後兩位+端口号以外,其他直接複制。比如示例中的3017441834的含義就是該mysql所在伺服器ip位址為:*.*.124.182,mysql占用的端口是3306。

同時,需要保證/home/mysql/log目錄存在,mysql的起停使用者必須擁有對該目錄的權限。

(4) 快速重新開機mysql生産執行個體,然後登入mysql檢視配置是否生效。

mysql資料庫都支援下面語句來停止執行個體:

mysqladmin -h127.0.0.1 -uroot -p3306 shutdown

檢視配置生效與否采用類似下列的語句進行檢查:

show variables like ’ log-bin%’

(5) 如果配置在生産執行個體生效,同樣的操作請在備用執行個體也操作一遍;

(6) 執行flush tables with read lock鎖定生産執行個體;

(7) 将生産執行個體的資料同步到備用執行個體,至少有兩種方案:對于生産執行個體與備用執行個體部署完全一樣的,可以直接将datadir目錄下所有檔案和目錄遠端複制到備用執行個體。對于生産執行個體和備用執行個體部署并不相同的,可以采用mysqldump将生産執行個體資料按db導出,然後再導入到備用執行個體中。整個過程生産執行個體不能解鎖;

(8) 解鎖生産執行個體:unlock tables;

(9) 查詢生産執行個體的master狀态,記錄下來binlog日志檔案名以及對應的position編号;

(10) 在備用執行個體執行以下語句:

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_master_timeout = 10000;

set global rpl_semi_sync_slave_enabled = 1;

grant replication slave,replication client on . to repuser@'%'identified by 'repuser';

這裡,預設repuser的密碼也是repuser,但是mysql5.7版本的強制要求,密碼複雜度必須比較高,是以密碼需要設定成複雜密碼。

change master to master_host='生産執行個體ip',master_port=3306(生産執行個體端口),master_user='repuser',master_password='repuser', master_log_file=’步驟9記錄下的binlog檔案名’, master_log_pos=’步驟9記錄下的binlog position編号’;

(11) 啟動備用執行個體slave,從生産執行個體複制資料。執行:start slave

(12) 檢查備用執行個體slave狀态:show slave status \g;重點看兩個參數:

slave_io_running和slave_sql_running,如果這兩個參數值都為yes。則配置正确,已經開始複制;

(13) 接下來配置從備用執行個體到生産執行個體的反向資料複制,在備用執行個體檢查master狀态:show master status;同樣記錄下binlog檔案名和位點資訊;

(14) 在生産執行個體重複步驟10-12完成反向複制配置。

(15) 結合slb進行業務測試,觀察生産執行個體的資料是否實時同步到備用執行個體;

(16) 最後需要向所有執行個體的/etc/my.cnf檔案添加以下内容:

rpl_semi_sync_master_enabled=on

rpl_semi_sync_slave_enabled=on

同時,我們将備用執行個體設成隻讀狀态:

set global read_only=1

3.災備切換流程

在ECS上自建MySQL手工容災環境

流程圖裡a執行個體代表生産執行個體,執行個體b代表備用執行個體。

(1) 當a執行個體發生故障時,首先考慮重新開機或者修複a,如果在短時間(30分鐘内)執行個體a能正常啟動,且啟動日志和業務側檢查沒有問題,那麼證明業務恢複正常,緊急處理成功;

(2) 如果執行個體a緊急重新開機成功,但是發現日志中有報錯,請分析日志報錯,判斷問題的影響範圍和大小,以決定忽略報錯或者修複報錯。如果在30分鐘内完成,依然可以認為業務成功恢複;

(3) 如果緊急重新開機執行個體a成功,日志中的報錯無法在30分鐘内修複,那麼我們啟動切換流程。即:

将備用執行個體可讀可寫打開:set global read_only=0

在slb将a執行個體的權重從100調成0,将b執行個體的權重從0調成100。保證業務先恢複起來;

(4) 執行個體b升成主執行個體對外提供服務時,我們在背景盡快想辦法修複a執行個體,如果a執行個體修複成功,檢查ba兩個執行個體之間的複制關系是否正常,如果複制恢複正常,我們的緊急處理結束;

(5) 如果執行個體b生成主執行個體對外提供服務時,盡管我們修複了執行個體a。但是兩個執行個體間的複制關系無法再恢複正常,請根據2.3節中的步驟重新配置主從複制;

(6) 如果執行個體a在發生故障時完全無法恢複,比如ecs已經不能啟動。那麼直接進入切換流程,将執行個體b更新成主執行個體。然後在背景緊急處理和恢複原來的a執行個體。

4.mysql同步失敗修複

4.1.同步初始化失敗

在從庫上面執行:show slave status\g;

正常情況:

在ECS上自建MySQL手工容災環境

錯誤情況:有no出現。

修複方式:

在主庫上面執行:

reset master;

在從庫上面執行:

stop slave;

reset slave;

change master to master_host='10.101.3.10',master_port=3301,master_user='repuser',master_password='repuser',master_auto_position=1;

4.2.同步了部分資料中斷

在從庫上面執行 show slave status\g;

例如:

在ECS上自建MySQL手工容災環境

對于slave_sql_running: no 的情況可以做如下處理:

slave stop;

set global sql_slave_skip_counter = 1;

slave start;

然後通過show slave status\g; 檢查是否有兩個yes。