Azure Database for MySQL 多云容灾
大家好,今天以此小文来说一说 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