MySQL 主从复制架构之单主模型与半同步复制
MySQL 集群架构模型
单主模型特性:
- 主节点打开二进制日志
- 从节点打开中继日志
- 从节点启动两个线程:IO线程用来向主节点申请主节点的二进制日志并保存至本地的中继日志,SQL线程用来读取中继日志的SQL语句并在本地执行,复现主节点的执行状态
双主模型特性:
- 两个节点互为主从
- 分别开启二进制日志和中继日志
- 分别启用两个线程:IO线程和SQL线程
一主多从架构实现示例:
假设主节点已经运行一段时间,其二进制日志中已保存很多SQL语句条目,现在建立一个主从架构的数据库
- 准备一个主节点和一个从节点,IP分别为172.16.50.9和172.16.50.10,
#在两台主机上分别同步时间
ntpdate 172.16.0.1
在实际生产环境中,如果主服务器已经运行一段时间,其二进制日志很大时,为了能让从服务器尽快追赶上主服务器,一般会对主节点服务器进行一次全量备份,将该全量备份在从节点服务器上恢复数据
主从服务器二者的MySQL程序版本不一致时:主服务器的MySQL版本可以低于从服务器,但不可以高于从服务器的MySQL版本
修改配置文件,对每个节点设置唯一的节点ID,主节点启用二进制日志,从节点启用中继日志
- 主节点配置
#修改配置文件
vim /etc/my.cnf.d/server.cnf
#仅需修改mysqld配置段
[mysqld]
innodb_file_per_table=ON
skip_name_resolve=ON
#修改server_id
server_id=1
#主节点启用二进制日志
log_bin=master-log
#启动mariadb服务
systemctl start mariadb;ss -tnl
- 从节点配置
假如该从节点有可能会在主节点宕机时成为新的主节点,也应该开启二进制日志
从节点应该设置为只读,但是,此处设置的只读仅对没有特殊权限的普通用户有效,对root等用户来说依然可写
#修改配置文件
vim /etc/my.cnf.d/server.cnf
#仅需修改mysqld配置段
[mysqld]
innodb_file_per_table=ON
skip_name_resolve=ON
#修改server_id
server_id=2
#从节点启用中继日志
relay_log=relay-log
read_only=ON
主节点服务器登录本地MySQL客户端执行操作
- 在主节点创建一个具有读取并请求二进制日志内容权限的账号供从节点登录从而执行复制操作
#创建用户
GRANT REPLICATION CLIENT,REPLICATION SLAVE ON *.* TO 'repluser'@'172.16.50.%' IDENTIFIED BY 'replpass';
#刷新并查看权限
FLUSH PRIVILEGES;
SHOW GRANTS FOR 'repluser'@'172.16.50.%'\G;
- 查看当前的二进制日志的名称和位置
SHOW MASTER STATUS;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-log.000006 | 497 | | |
+-------------------+----------+--------------+------------------+
从节点服务器登录本地MySQL客户端执行操作
- 在从节点服务器上指定主节点服务器的相关信息
CHANGE MASTER TO MASTER_HOST='172.16.50.9',MASTER_USER='repluser',MASTER_PASSWORD='replpass',MASTER_PORT=3306,MASTER_LOG_FILE='master-log.000006',MASTER_LOG_POS=497;
- 查看从节点信息
SHOW SLAVE STATUS\G;
#信息如下:
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 172.16.50.9 #主节点的主机名
Master_User: repluser #主节点上的具有复制权限的用户
Master_Port: 3306 #连接主节点的端口
Connect_Retry: 60 #连接重试时间
Master_Log_File: master-log.000006 #主节点使用的二进制日志名
Read_Master_Log_Pos: 497 #主节点的二进制日志执行语句的位置
Relay_Log_File: relay-log.000001 #从节点中继日志名
Relay_Log_Pos: 4 #从节点中继日志位置
Relay_Master_Log_File: master-log.000006
Slave_IO_Running: No #是否启动了IO线程
Slave_SQL_Running: No #是否启动了SQL线程
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: 497
Relay_Log_Space: 245
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: NULL #从节点落后于主节点的秒数
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0 #最后一次的IO线程的错误编号
Last_IO_Error: #最后一次IO线程的错误信息内容
Last_SQL_Errno: 0 #最后一次的SQL线程的错误编号
Last_SQL_Error: #最后一次SQL线程的错误信息内容
Replicate_Ignore_Server_Ids:
Master_Server_Id: 0 #主节点的server_id
1 row in set (0.00 sec)
- 启动从节点的IO线程和SQL线程,让从节点连接至主节点
#启用IO线程和SQL线程
START SLAVE;
#再次查看主从信息,注意与启动线程前的状态信息进行对比
SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.16.50.9
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-log.000006
Read_Master_Log_Pos: 497
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 530
Relay_Master_Log_File: master-log.000006
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: 497
Relay_Log_Space: 818
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: 0
Master_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
1 row in set (0.00 sec)
- 启动两个线程后查看mariadb程序错误日志的记录信息
tail /var/log/mariadb/mariadb.log
170716 0:21:11 [Note] /usr/libexec/mysqld: ready for connections.Version: '5.5.52-MariaDB' socket: '/var/lib/mysql/mysql.sock' port: 3306 MariaDB Server
170716 0:40:39 [Note] 'CHANGE MASTER TO executed'. Previous state master_host='', master_port='3306',master_log_file='', master_log_pos='4'. New state master_host='172.16.50.9',master_port='3306', master_log_file='master-log.000006', master_log_pos='497'.
170716 0:54:38 [Note] Slave SQL thread initialized, starting replication in log 'master-log.000006' at position497, relay log './relay-log.000001' position: 4
170716 0:54:38 [Note] Slave I/O thread: connected to master 'repluser@172.16.50.9:3306',replication started in log 'master-log.000006' at position 497
至此,主从复制已配置完成。
复制时应该注意的问题:
1、从服务设定为“只读”;
在从服务器启动read_only,但仅对非SUPER权限的用户有效;
阻止所有用户:
mysql> FLUSH TABLES WITH READ LOCK;
2、尽量确保复制时的事务安全
【可能导致服务启动失败】
在master节点启用参数:
sync_binlog = ON
如果用到的是InnoDB存储引擎:
innodb_flush_logs_at_trx_commit=ON
innodb_support_xa=ON
3、从服务器意外中止时尽量避免自动启动复制线程
4、从节点:设置参数
【可能导致服务启动失败】
sync_master_info=ON
sync_relay_log_info=ON
主从架构的半同步复制
- 分别在主从节点上执行执行安装插件命令
#在主节点服务器上登录mysql客户端,执行:
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
#在从节点服务器上登录mysql客户端,执行:
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
#查看插件的加载状态
SHOW PLUGINS;
启用插件
- 主节点
#查看插件运行状态
SHOW GLOBAL VARIABLES LIKE '%semi_sync%';
+------------------------------------+-------+
| 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 |
+------------------------------------+-------+
#启用插件
SET @@global.rpl_semi_sync_master_enabled=ON;
- 从节点
#查看插件运行状态
SHOW GLOBAL VARIABLES LIKE '%semi%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
#启用插件
SET @@global.rpl_semi_sync_slave_enabled=ON;
- 在从节点重启IO线程
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;
- 在主节点导入一些数据,查看同步效果
ls /root/hellodb.sql;cd /root
mysql < hellodb.sql
#登录mysql客户端,查看同步效果
SHOW GLOBAL STATUS LIKE 'rpl%';
+--------------------------------------------+-------------+
| Variable_name | Value |
+--------------------------------------------+-------------+
| Rpl_semi_sync_master_clients | 1 |
| Rpl_semi_sync_master_net_avg_wait_time | 684 |
| Rpl_semi_sync_master_net_wait_time | 23974 |
| Rpl_semi_sync_master_net_waits | 35 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 907 |
| Rpl_semi_sync_master_tx_wait_time | 30838 |
| Rpl_semi_sync_master_tx_waits | 34 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 35 |
| Rpl_status | AUTH_MASTER |
+--------------------------------------------+-------------+