大家好,今天以此小文來說一說 Azure Database for MySQL 的多雲容災。作為任何一家雲的 RDS PaaS 服務所有的可用性都是用白紙黑字的 SLA 支撐的,無論是4個9還是 n 個9 都意味着有 outage 的可能性, Everything fails all the time. 對於 RDS 數據庫服務,如果服務實現 outage 意味着有可能存在不可預期的 RTO。原因很簡單,對於 PaaS 服務屬於沙箱式的服務,當初出現故障所需的故障恢復時間由雲服務商決定,對於用戶只能在一邊默默祈禱早日恢復。對於任何一個業務應用,從業務重要性角度出發,會提出不同的 SLA 的要求,從而轉化為系統架構時需求。對於 Mission Critical 的業務應用,用戶應該從最初的架構設計角度考慮所采用的產品、技術棧及其可能對 SLA 帶來的影響因素。對於 Azure Database for MySQL 而言一樣存在着極端情況下無法使用的情況,那我們如何來實現高可用架構,更好的應對 Mission Critical 業務應用對可用性的要求。下面我們來假設 Azure Database for MySQL 在極端條件下整個 PaaS 服務在 Azure 內的所有 Region 都無法使用了,或者當前所使用的 Azure Database for MySQL 所在 Region 內該服務不可用了,如何保證數據服務以及業務應用的可用性?雞蛋不要放在一個籃子里,1. 可否在非 PaaS 服務內有一份備份可用的數據服務,2. 可否在其它雲平台有一份備份可用的數據服務。Azure Database for MySQL 是以社區版本 MySQL 為基礎開發的 PaaS 服務,其原生同樣支持 Binlog 的同步機制,后面我們來介紹一下如何在 Azure Database for MySQL 上開啟 Binlog,並在其它 MySQL 部署中與其進行同步。
1. 開啟 Azure Database for MySQL 的 Binlog
默認 Azure Database for MySQL 在無 Replica 副本情況下 Binlog 是關閉的,可以通過添加 Replica 副本的方式來間接開啟 Binlog,開啟完畢后將 Replica 服務刪除。
登入 Azure Database for MySQL 查看 Binlog 狀態
mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 2981 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.02 sec)
mysql> show binary logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 2981 | +------------------+-----------+ 1 row in set (0.03 sec)
查看 Azure Database for MySQL 的 server id,記錄后續使用
mysql> SHOW VARIABLES LIKE 'server_id'; +---------------+------------+ | Variable_name | Value | +---------------+------------+ | server_id | 2431497671 | +---------------+------------+ 1 row in set (0.03 sec)
2. 配置外部 MySQL Slave 副本
MySQL的安裝步驟此文略去,大家可以參閱 MySQL 的官網手冊。
修改 my.cnf 配置 Slave Server ID,在與 Azure Database for MySQL 進行同步時,Slave 節點通過 server id 作為自己的身份標識,與主節點進行同步,要保證 server id 與 Azure Database for MySQL 所使用 id 不同。挑選 server id 與第一步中所獲取的 server id 不同,並在 mysql 的 my.cnf 上進行配置:
#
# The MySQL database server configuration file.
#
# You can copy this to one of:
# - "/etc/mysql/my.cnf" to set global options,
# - "~/.my.cnf" to set user-specific options.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
#
# * IMPORTANT: Additional settings that can override those from this file!
# The files must end with '.cnf', otherwise they'll be ignored.
#
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
[mysqld] server-id=2
3. 配置 MySQL 同步
如果 Azure Database for MySQL 已經存在數據,通過 mysqldump 將當前數據庫數據導出,並在 Slave 側做導入。操作過程中建議將數據庫置入只讀模式(FLUSH TABLES WITH READ LOCK;),這樣避免在操作過程中產生的數據一致性問題。下面以名稱為 demo 的數據庫為例
#dump database mysqldump -h <mysqlinstancename>.mysql.database.chinacloudapi.cn -u <username>@<mysqlinstancename> -p --databases demo > demo_dump.sql #import the dump to Slave mysql mysql -h <slavehostaddress> -u <username> -p < ./demo_dump.sql
在 Azure Database for MySQL 中查看 binlog 文件名稱及同步起始位置
mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 2981 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.02 sec)
第一列為文件名稱,第二列為起始位置。
在 Slave Mysql 中配置 Azure Database for MySQL Master 同步信息,其中需要注意 MASTER_SSL 一定要進行設置, Azure Database for MySQL Master 默認是只允許 SSL 連接的,如果想通過非 SSL 方式連接,需要在 Azure Database for MySQL Master 進行設置
mysql> CHANGE MASTER TO -> MASTER_HOST='master_host_name', -> MASTER_USER='replication_user_name', -> MASTER_PASSWORD='replication_password', -> MASTER_LOG_FILE='recorded_log_file_name', -> MASTER_LOG_POS=recorded_log_position, -> MASTER_SSL=1;
配置完成后,查看同步狀態,其中 Slave_IO_State: Waiting for master to send event 表示同步設置成功,等待同步
mysql> show slave status \G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: binlogdemo.mysql.database.chinacloudapi.cn Master_User: azuredemo@binlogdemo Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 2981 Relay_Log_File: pledemo-relay-bin.000003 Relay_Log_Pos: 649 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: No Replicate_Do_DB: Replicate_Ignore_DB: mysql Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 1064 Last_Error: Error 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FIREWALL_RULES' at line 1' on query. Default database: ''. Query: 'FLUSH FIREWALL_RULES' Skip_Counter: 0 Exec_Master_Log_Pos: 2833 Relay_Log_Space: 1756 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: Yes Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: NULL Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 1064 Last_SQL_Error: Error 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FIREWALL_RULES' at line 1' on query. Default database: ''. Query: 'FLUSH FIREWALL_RULES' Replicate_Ignore_Server_Ids: Master_Server_Id: 2431497671 Master_UUID: b01ec3a3-6e31-11ea-90fd-fc670e102793 Master_Info_File: /var/lib/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: 200325 05:43:17 Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec)
4. 設置同步過濾
前面介紹到 Azure Database for MySQL Master 采用社區版本進行開發,在上面微軟也進行了相應的擴展功能,這些功能配置信息也是以表數據的形式存儲在 MySQL 內部的,所以比如在 Azure Portal 上對 MySQL 進行的一些配置調整也可能產生 Binlog,這些 Binlog 信息屬於非標的 Binlog,所以在 Slave 端同步可能產生錯誤,舉例在 Azure Database for MySQL Master 上設置訪問白名單,該操作也會產生 binlog
# at 2637 #200325 5:43:17 server id 2431497671 end_log_pos 2712 CRC32 0x3aef2b23 Table_map: `mysql`.`__firewall_rules__` mapped to number 11 # at 2712 #200325 5:43:17 server id 2431497671 end_log_pos 2802 CRC32 0xddca4717 Write_rows: table id 11 flags: STMT_END_F BINLOG ' de96XhPHte2QSwAAAJgKAAAAAAsAAAAAAAEABW15c3FsABJfX2ZpcmV3YWxsX3J1bGVzX18ABg8P DwMSEgiAAYcAhwAAAAAjK+86 de96Xh7Hte2QWgAAAPIKAAAAAAsAAAAAAAEAAgAGP8AKAHdoaXRlbGlzdDMNNDAuNzMuMTI3LjIw NQ00MC43My4xMjcuMjA1AAAAAJml8lrRmaXyWtEXR8rd '/*!*/; ### INSERT INTO `mysql`.`__firewall_rules__` ### SET ### @1='whitelist3' ### @2='40.73.127.205' ### @3='40.73.127.205' ### @4=0 ### @5='2020-03-25 05:43:17' ### @6='2020-03-25 05:43:17'
此類信息都存在名稱為 mysql 的數據庫內,可以通過對同步設置過濾條件,將與該數據庫相關的 binlog 過濾掉
CHANGE REPLICATION FILTER REPLICATE_IGNORE_DB = (mysql);
5. 驗證。在 Azure Database for MySQL Master 側的測試表中插入數據,檢查 Slave 同步正常。
上面介紹的操作是通過以一個虛擬機來搭建一個 MySQL Slave 節點,通過 binlog 復制的方式與 Azure Database for MySQL Master 進行同步。該方式在災難發生時數據庫內的數據為熱數據可以立即使用,除此之外也可以考慮冷備方案,將 Binlog 以文件方式保存,當災難發生時通過 binlog 來恢復一個數據庫出來。冷備方案涉及數據狀態過程,所以會產生額外的恢復時間,該方式可以通過 mysqlbinlog 命令工具將 Azure Database for MySQL Master 的 binlog 導出至文件路徑進行存儲。命令中最后的 binlog 名稱參數,可參考前面在 Azure Database for MySQL 中查看 binlog 文件名稱及同步起始位置步驟獲得,以最后一次 mysqldump 作為一個checkpoint,后面的增量數據都已 binlog 進行保存。
mysqlbinlog -R -h <mysqlhost> -u <username> -p --stop-never --raw mysql-bin.000001
好了,今天就給大家寫到這里,希望通過上面的介紹對大家的 MySQL 高可用設計有所幫助。如果大家對 binlog sync 實現的原理感興趣,可以訪問 1. Binlog 介紹: https://dev.mysql.com/doc/internals/en/binary-log-overview.html 2. MySQL Binlog Replication Configuration:https://dev.mysql.com/doc/refman/5.7/en/replication.html 3. mysqlbinlog tool:https://dev.mysql.com/doc/refman/5.7/en/mysqlbinlog.html#option_mysqlbinlog_raw