目录
一、集群技术
1、集群目的
2、类型
3、MySQL复制技术原理示意图
二、集群案例
例1:一主一从(1)(M-S)
例2:一主一从(2)(M-S)
例3:双主双从(MM-SS)四台服务器
负载均衡 解决高并发
高可用HA 服务可用性
远程灾备 数据有效性
M 主
M-S 主-从
M-S-S... 主-多从
M-M 双主
M-M-S-S 双主双从
概念:
在主库上把数据更改(DDL DML DCL)记录到二进制日志(Binary Log)中;
备库I/O线程将主库上的日志复制到自己的中继日志(Relay Log)中;
备库SQL线程读取中继日志中的时间,将其放到备库数据库之上。
例1:一主一从(1)(M-S)
主(master1)
//准备好一台新mysql服务器,准备好域名解析,两台都要做 [root@master1 ~]# cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.172.174 master1 192.168.172.166 slave1 //准备数据1(验证主从同步使用) mysql> create table master1db.tab1(name char(50)); Query OK, 0 rows affected (0.02 sec) mysql> insert into master1db.tab1 values(111); Query OK, 1 row affected (0.03 sec) mysql> insert into master1db.tab1 values(222); Query OK, 1 row affected (0.01 sec) mysql> select * from master1db.tab1; +------+ | name | +------+ | 111 | | 222 | +------+ 2 rows in set (0.00 sec)
//开启二进制日志 [root@master1 ~]# vim /etc/my.cnf [mysqld] log_bin server_id=1 [root@master1 ~]# systemctl restart mysqld [root@master1 ~]# ls /var/lib/mysql master1-bin.000001 //可以看到里面有这个文件 //创建复制用户 [root@master1 ~]# mysql -uroot -p'Qian@123' mysql> grant replication slave,replication client on *.* to 'rep'@'192.168.172.%' identified by 'Qian@123'; //备份master数据库的数据 [root@master1 ~]# mysqldump -p'Qian@123' --all-databases --single-transaction --master-data=2 --flush-logs > `date +%F`-mysql-all.sql [root@master1 ~]# ls 2022-10-14-mysql-all.sql //把备份传送到slave1 [root@master1 ~]# scp -r 2022-10-14-mysql-all.sql slave1:/tmp The authenticity of host 'slave1 (192.168.172.166)' can't be established. ECDSA key fingerprint is SHA256:HumQuxOX0NOaT9s/Lx2oTdcp3WZ+HnK0xD0tJQJTm54. ECDSA key fingerprint is MD5:ef:0b:e0:47:5d:dc:ce:0e:d7:e4:e3:55:94:0a:63:ac. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'slave1,192.168.172.166' (ECDSA) to the list of known hosts. root@slave1's password: 2022-10-14-mysql-all.sql 100% 861KB 50.2MB/s 00:00 //到slave1看一下,备份成功 [root@slave1 ~]# ls /tmp/ 2022-10-14-mysql-all.sql
//准备数据2(验证主从同步使用) mysql> insert into master1db.tab1 values(333); Query OK, 1 row affected (0.01 sec) mysql> insert into master1db.tab1 values(444); Query OK, 1 row affected (0.01 sec) mysql> select * from master1db.tab1; +------+ | name | +------+ | 111 | | 222 | | 333 | | 444 | +------+ 4 rows in set (0.00 sec)
从(slave1)
//测试rep用户是否可用,预防账户有问题,记得关闭防火墙,不关防火墙是登不进去的 [root@slave1 ~]# mysql -h master1 -urep -p'Qian@123' mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | +--------------------+ 1 row in set (0.01 sec)
//启动服务器序号 [root@slave1 ~]# vim /etc/my.cnf [mysqld] server_id=2 [root@slave1 ~]# systemctl restart mysqld //测试服务器是否修改正确,能否正常登录 [root@slave1 ~]# mysql -uroot -p'Linn@123' mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.01 sec) //手动同步数据,暂停二进制日志 mysql> set sql_log_bin=0; Query OK, 0 rows affected (0.00 sec) //还原二进制文件 mysql> source /tmp/2022-10-14-mysql-all.sql mysql> select * from master1db.tab1; +------+ | name | +------+ | 111 | | 222 | +------+ 2 rows in set (0.00 sec) //注意,二进制日志的位置,应该参照主服务器备份时生成的新位置,查看一下备份文件2022-10-14-mysql-all.sql的第22行 mysql> change master to master_host='master1',master_user='rep',master_password='Qian@123',master_log_file='master1-bin.000002',master_log_pos=154; Query OK, 0 rows affected, 2 warnings (0.02 sec) //启动从设备 mysql> start slave; Query OK, 0 rows affected (0.01 sec) //查看数据 mysql> select * from master1db.tab1; //可以看到数据已经同步过来了 +------+ | name | +------+ | 111 | | 222 | | 333 | | 444 | +------+ //返回主服务器master1更新数据,在从服务器slave1观察是否同步 //master1 mysql> insert into master1db.tab1 values(555); Query OK, 1 row affected (0.01 sec) mysql> insert into master1db.tab1 values(666); Query OK, 1 row affected (0.01 sec) //slave1 mysql> select * from master1db.tab1; //同步成功 +------+ | name | +------+ | 111 | | 222 | | 333 | | 444 | | 555 | | 666 | +------+ 6 rows in set (0.00 sec) //查看启动状态,如果遇到什么问题,可以看一下状态信息 mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: master1 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: master1-bin.000002 Read_Master_Log_Pos: 1186 Relay_Log_File: slave1-relay-bin.000002 Relay_Log_Pos: 1354 Relay_Master_Log_File: master1-bin.000002 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: 1186 Relay_Log_Space: 1562 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 Master_UUID: 20555f91-4ad8-11ed-a8ff-000c299c92f3 Master_Info_File: /var/lib/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: 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)
例2:一主一从(2)(M-S)
跟例1功能相同,不同之处,使用了“gtid_mode=ON enforce_gtid_consistency=1” 该属性自动记录position位置,不需要手动指定了
主(master1)
//重置slave1数据库 [root@slave1 ~]# systemctl stop mysqld [root@slave1 ~]# rm -rf /var/lib/mysql/* [root@slave1 ~]# systemctl start mysqld [root@slave1 ~]# grep password /var/log/mysqld.log 2022-10-15T04:16:49.578713Z 1 [Note] A temporary password is generated for root@localhost: hZv+)vtVl3Cq [root@slave1 ~]# mysqladmin -p'hZv+)vtVl3Cq' password 'Linn@123' [root@slave1 ~]# mysql -p'Linn@123'
//master1配置 //启动二进制日志,服务器ID,GTID [root@master1 ~]# vim /etc/my.cnf [mysqld] log_bin server_id=1 gtid_mode=ON enforce_gtid_consistency=1 [root@master1 ~]# systemctl restart mysqld //授权复制用户rep,上面已经做过了,这里就不做了 //备份数据 [root@master1 ~]# mysqldump -p'Qian@123' --all-databases --single-transaction --master-data=2 --flush-logs > `date +%F`-mysql-all.sql [root@master1 ~]# scp 2022-10-15-mysql-all.sql slave1:/tmp root@slave1's password: 2022-10-15-mysql-all.sql 100% 861KB 28.1MB/s 00:00 //模拟数据变化 [root@master1 ~]# mysql -uroot -p'Qian@123' mysql> insert into master1db.tab1 values(7777); Query OK, 1 row affected (0.01 sec) mysql> insert into master1db.tab1 values(8888); Query OK, 1 row affected (0.01 sec) mysql> select * from master1db.tab1; +------+ | name | +------+ | 111 | | 222 | | 333 | | 444 | | 555 | | 666 | | 7777 | | 8888 | +------+ 8 rows in set (0.00 sec)
从(slave1)
//测试rep用户是否可用 [root@slave1 ~]# mysql -h master1 -urep -p'Qian@123' mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | +--------------------+ 1 row in set (0.00 sec) //启动二进制日志,服务器ID,GTID [mysqld] log_bin server_id=2 gtid_mode=ON enforce_gtid_consistency=1 [root@slave1 ~]# systemctl restart mysqld //恢复手动同步数据 [root@slave1 ~]# mysql -p'Linn@123' mysql> set sql_log_bin=0; //临时关闭二进制日志 Query OK, 0 rows affected (0.00 sec) mysql> source /tmp/2022-10-15-mysql-all.sql mysql> select * from master1db.tab1; +------+ | name | +------+ | 111 | | 222 | | 333 | | 444 | | 555 | | 666 | +------+ 6 rows in set (0.00 sec) //设置主服务器 mysql> change master to -> master_host='master1', -> master_user='rep', -> master_password='Qian@123', -> master_auto_position=1; Query OK, 0 rows affected, 2 warnings (0.02 sec) mysql> start slave; Query OK, 0 rows affected (0.01 sec) mysql> select * from master1db.tab1; +------+ | name | +------+ | 111 | | 222 | | 333 | | 444 | | 555 | | 666 | | 7777 | | 8888 | +------+ 8 rows in set (0.00 sec) //返回主服务器(master1)更新数据,在从服务器(slave1)观察是否同步 //master1 mysql> insert into master1db.tab1 values(999); Query OK, 1 row affected (0.01 sec) mysql> insert into master1db.tab1 values(1010); Query OK, 1 row affected (0.01 sec) //slave1 mysql> select * from master1db.tab1; +------+ | name | +------+ | 111 | | 222 | | 333 | | 444 | | 555 | | 666 | | 7777 | | 8888 | | 999 | | 1010 | +------+ 10 rows in set (0.00 sec)
例3:双主双从(MM-SS)四台服务器
- 主操作
master2 到master2上面做一下上面slave1的操作,然后接着做下面的操作
[root@master2 ~]# mysql -p'Qian@12345' //在master2上进行授权 mysql> grant replication slave,replication client on *.* to 'rep'@'192.168.172.%' identified by 'Qian@123'; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> flush privileges; Query OK, 0 rows affected (0.01 sec)
master1
[root@master1 ~]# mysql -p'Qian@123' mysql> change master to -> master_host='master2', -> master_user='rep', -> master_password='Qian@123', -> master_auto_position=1; Query OK, 0 rows affected, 2 warnings (0.02 sec) mysql> start slave; Query OK, 0 rows affected (0.03 sec) mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Connecting to master Master_Host: master2 //这里可以看到master1的主人为master2 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: Read_Master_Log_Pos: 4 Relay_Log_File: master1-relay-bin.000001 Relay_Log_Pos: 4 Relay_Master_Log_File: Slave_IO_Running: Connecting 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: 0 Relay_Log_Space: 154 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: 2003 Last_IO_Error: error connecting to master 'rep@master2:3306' - retry-time: 60 retries: 4 Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 0 Master_UUID: Master_Info_File: /var/lib/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: 221015 02:49:20 Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: 20555f91-4ad8-11ed-a8ff-000c299c92f3:1-4 Auto_Position: 1 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec)
现在测试一下maser1和master2是否可以同步,双主是否设置成功
//在master1的数据库中插入数据,在master2中查看数据 //master1 mysql> insert into master1db.tab1 values(123123); Query OK, 1 row affected (0.01 sec) //master2 mysql> select * from master1db.tab1; +--------+ | name | +--------+ | 111 | | 222 | | 333 | | 444 | | 555 | | 666 | | 7777 | | 8888 | | 999 | | 1010 | | 123123 | +--------+ 11 rows in set (0.00 sec)
//在master2的数据库中插入数据,在master1数据库中查看 //master2 mysql> insert into master1db.tab1 values(789789); Query OK, 1 row affected (0.01 sec) //master1 mysql> select * from master1db.tab1; +--------+ | name | +--------+ | 111 | | 222 | | 333 | | 444 | | 555 | | 666 | | 7777 | | 8888 | | 999 | | 1010 | | 123123 | | 789789 | +--------+ 12 rows in set (0.00 sec) //这里遇到一个问题,就是在master2中插入数据之后,在master1中并没有同步过来,有可能是因为前面临时关闭了二进制日志,后面没有开启二进制日志,我退出了一下数据库,重新进了一下,再插入数据,就同步了
- 从操作
//先备份一下master1的当前状态,然后把备份复制到slave [root@master1 ~]# mysqldump -p'Qian@123' --all-databases --single-transaction --master-data=2 --flush-logs > `date +%F-%H`-mysql-all.sql [root@master1 ~]# scp 2022-10-15-03-mysql-all.sql slave1:/tmp root@slave1's password: 2022-10-15-03-mysql-all.sql 100% 861KB 28.7MB/s 00:00 [root@master1 ~]# scp 2022-10-15-03-mysql-all.sql slave2:/tmp
slave1
//清一下slave1环境 //启动从服务器ID,GTID [root@slave1 ~]# mysql -p'Linn@123' < /tmp/mmss-mysql-all.sql [root@slave1 ~]# vim /etc/my.cnf [mysqld] server_id=3 gtid_mode=ON enforce_gtid_consistency=1 master-info-repository=TABLE relay-log-info-repository=TABLE //中继日志 [root@slave1 ~]# systemctl restart mysqld
//设置主服务器 [root@slave1 ~]# mysql -p'Linn@123' mysql> source /tmp/2022-10-15-03-mysql-all.sql mysql> change master to -> master_host='master1', -> master_user='rep', -> master_password='Qian@123', -> master_auto_position=1 for channel 'master1'; mysql> change master to -> master_host='master2', -> master_user='rep', -> master_password='Qian@123', -> master_auto_position=1 for channel 'master2'; Query OK, 0 rows affected, 2 warnings (0.01 sec) mysql> start slave; Query OK, 0 rows affected (0.00 sec) mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Master_Host: master1 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: Read_Master_Log_Pos: 4 Relay_Log_File: slave1-relay-bin-master1.000001 Relay_Log_Pos: 4 Relay_Master_Log_File: 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: 0 Relay_Log_Space: 154 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: 1236 Last_IO_Error: 0 Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1 Master_UUID: 20555f91-4ad8-11ed-a8ff-000c299c92f3 Master_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: 221015 04:14:36 Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: d9c78455-4c5e-11ed-9059-000c29c7c574:1 Auto_Position: 1 Replicate_Rewrite_DB: Channel_Name: master1 Master_TLS_Version: *************************** 2. row *************************** Slave_IO_State: Master_Host: master2 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: Read_Master_Log_Pos: 4 Relay_Log_File: slave1-relay-bin-master2.000001 Relay_Log_Pos: 4 Relay_Master_Log_File: 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: 0 Relay_Log_Space: 154 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: 1236 Last_IO_Error: 0 Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 2 Master_UUID: 79050a0d-4c52-11ed-b6ff-000c29fcfb13 Master_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: 221015 04:14:36 Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: d9c78455-4c5e-11ed-9059-000c29c7c574:1 Auto_Position: 1 Replicate_Rewrite_DB: Channel_Name: master2 Master_TLS_Version: 2 rows in set (0.00 sec)
slave2
//启动从服务器ID,GTID [root@slave2 ~]# vim /etc/my.cnf [mysqld] server_id=4 gtid_mode=ON enforce_gtid_consistency=1 master-info-repository=TABLE relay-log-info-repository=TABLE [root@slave2 ~]# systemctl restart mysqld
//设置主服务器 [root@slave2 ~]# mysql -p'Qian@1234' mysql> source /tmp/2022-10-15-03-mysql-all.sql mysql> change master to -> master_host='master1', -> master_user='rep', -> master_password='Qian@123', -> master_auto_position=1 for channel 'master1'; Query OK, 0 rows affected, 2 warnings (0.03 sec) mysql> change master to -> master_host='master2', -> master_user='rep', -> master_password='Qian@123', -> master_auto_position=1 for channel 'master2'; Query OK, 0 rows affected, 2 warnings (0.02 sec) mysql> start slave; Query OK, 0 rows affected (0.02 sec)
最后在主服务器数据库中插入数据,查看从服务器就可以看到数据已经同步