MySQL(六)

集群

单节点数据库

优点:适合数据量小的网站,如企业网站。

缺点:单个数据库无法满足日益增长的读写请求;

为什么要使用集群

高可用性:站点高可用,冗余站点;服务高可用,冗余服务;数据高可用,冗余数据。

负载均衡:切换某服务访问某节点,分摊单个节点的数据库压力

可伸缩性:新增数据库节点便利,方便扩容。

MySQL集群缺点

  • 网络分裂:群集还可能由于网络故障而拆分为多个部分,每部分内的节点相互连接,但各部分之间的节点失去连接。
  • 脑裂:导致数据库节点彼此独立运行的集群故障称为“脑裂”。这种情况可能导致数据不一致,并且无法修复,例如当两个数据库节点独立更新同一表上的同一行时

MySQL集群中各实例的数据同步,均基于mysql的复制机制。

原理

MySQL(六)_第1张图片

第一步:主库开启bin-log日志: ** 主库需要设置开启记录二进制日志,提交数据更新的事务之前将更新的事件记录都二进制日志中,后才进行事务提交。

第二步:备库建立IO线程连接: ** 备库创建IO线程与主库创建连接,主库上启动一个binlog-dump线程。该线程会读取主库二进制事件,该线程不会对事件进行轮询。如果从库数据与主库已经保持一致后,该线程进入休眠状态,一旦主库有新事件会以信号量唤醒binlog-dump线程。备库IO线程会将事件写入到中继日志(relay-log)中。

第三步:SQL线程重放数据:**SQL线程执行最后一步,从中继日志中获取事件并在备库中执行,从而实现数据库的更新。

类型

M-S:一主一从

M-S-S:一主多从

M-M:双主

M-M-S-S:双主多从

实验

M-S实践(手动指定POS位置)

环境

master1——192.168.28.141——mysql8.0.34——数据库已有数据

[root@master1 ~]# mysql -uroot -p'Admin.123'
mysql> create database class;
Query OK, 1 row affected (0.00 sec)
mysql> create table class.stu (id int,name varchar(50));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into class.stu values(1,'a');
Query OK, 1 row affected (0.05 sec)

mysql> select * from class.stu;
+------+------+
| id   | name |
+------+------+
|    1 | a    |
+------+------+
1 row in set (0.00 sec)

slave1——192.168.28.143——mysql8.0.34——数据库没有数据

master1

开启二进制日志,指定master的server-id标识为1

[root@master1 ~]# echo  -e "log_bin \nserver-id=1" >> /etc/my.cnf
[root@master1 ~]# systemctl restart mysqld

创建复制用户并授权

[root@master1 ~]# mysql -uroot -p'Admin.123'
mysql> create user 'rep'@'192.168.28.%' identified by 'Admin.123';
Query OK, 0 rows affected (0.05 sec)

mysql> grant replication slave on *.* to 'rep'@'192.168.28.%';
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> show grants for 'rep'@'192.168.28.%';
+--------------------------------------------------------+
| Grants for [email protected].%                            |
+--------------------------------------------------------+
| GRANT REPLICATION SLAVE ON *.* TO `rep`@`192.168.28.%` |
+--------------------------------------------------------+
1 row in set (0.01 sec)

备份

[root@master1 ~]# mysqldump -uroot -p'Admin.123' -A --single-transaction --source-data=2 --flush-logs > `date +'%F-%T'-all.sql`
[root@master1 ~]# ls
2023-09-10-21:20:02-all.sql  anaconda-ks.cfg

[root@master1 ~]# cat 2023-09-10-21\:20\:02-all.sql
...
-- CHANGE MASTER TO MASTER_LOG_FILE='master1-bin.000003', MASTER_LOG_POS=157;

将备份文件传输至slave1上

[root@master1 ~]# scp ./2023-09-10-21\:20\:02-all.sql root@slave1:/root

slave1

[root@slave1 ~]# ls
2023-09-10-21:20:02-all.sql  anaconda-ks.cfg

#测试能否以复制用户登录master1的数据库
[root@slave1 ~]# mysql -h master1 -urep -p'Admin.123'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
...

#设置slave1的server-id
[root@slave1 ~]# echo "server-id=2" >> /etc/my.cnf
[root@slave1 ~]# systemctl restart mysqld

恢复数据

[root@slave1 ~]# mysql -uroot -p'Admin.123'
mysql> set sql_log_bin=0;    #关闭二进制日志,避免产生因恢复操作出现的日志
mysql> source /root/2023-09-10-21:20:02-all.sql    #导入数据
mysql> change master to master_host='master1',master_user='rep',master_password='Admin.123',master_log_file='/var/lib/mysql/master1-bin.000003',master_log_pos=157;
mysql> start slave;    #开启同步

#查看从数据库的状态
mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: master1
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master1-bin.000003
          Read_Master_Log_Pos: 157
               Relay_Log_File: slave1-relay-bin.000002
                Relay_Log_Pos: 328
        Relay_Master_Log_File: master1-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
...
  • Slave_IO_State: 显示从服务器I/O线程的当前状态。
  • Slave_IO_Running: 表示从服务器的I/O线程是否正在运行,如果值为"YES",则说明I/O线程正常运行。
  • Slave_SQL_Running: 表示从服务器的SQL线程是否正在运行,如果值为"YES",则说明SQL线程正常运行。
  • Master_Log_File: 显示主服务器当前二进制日志的位置。
  • Read_Master_Log_Pos: 显示从服务器当前读取主服务器二进制日志的位置。
  • Relay_Log_File: 显示从服务器当前中继日志的位置。
  • Relay_Log_Pos: 显示从服务器当前中继日志的位置。
  • Connect_Retry: 显示从服务器尝试连接到主服务器的重试间隔时间(单位为秒)。

此时数据已保持一致

mysql> select * from class.stu;
+------+------+
| id   | name |
+------+------+
|    1 | a    |
+------+------+
1 row in set (0.01 sec)

 在master1中新增数据

mysql> insert into class.stu values(2,'b');
Query OK, 1 row affected (0.00 sec)

mysql> select * from class.stu;
+------+------+
| id   | name |
+------+------+
|    1 | a    |
|    2 | b    |
+------+------+
2 rows in set (0.00 sec)

查看slave1是否同步,已同步

mysql> select * from class.stu;
+------+------+
| id   | name |
+------+------+
|    1 | a    |
|    2 | b    |
+------+------+
2 rows in set (0.00 sec)

双主双从(自动记录POS位置)

双主避免单点故障。

gtid_mode=ON   是一种MySQL的特性,它为每个事务分配一个唯一的全局事务ID。这个选项用于启用GTID。在大多数情况下,你应该开启这个选项,因为它可以提供更好的复制和故障恢复功能。

enforce_gtid_consistency=1   这个选项确保了在MySQL服务器上所有线程和复制都严格遵守GTID的一致性。如果设置为1,那么MySQL将不允许在同一个会话中执行两次相同的事务。这对于确保数据的一致性非常有用。

数据库配置文件添加如下

log_bin

server-id=1   #每台服务器server-id 不一样

gtid_mode=ON

enforce_gtid_consistency=1

一、配置 master1 为 master2 的主服务器

master1——192.168.28.141

[root@master1 ~]# mysql -uroot -p'Admin.123'
mysql> create database class;
Query OK, 1 row affected (0.00 sec)

mysql> create table class.stu (id int,name varchar(50));
Query OK, 0 rows affected (0.01 sec)

mysql> insert into class.stu values(1,'wei');
Query OK, 1 row affected (0.09 sec)

mysql> select * from class.stu;
+------+------+
| id   | name |
+------+------+
|    1 | wei  |
+------+------+
1 row in set (0.00 sec)

[root@master1 ~]# vim /etc/my.cnf
...
log_bin
server-id=1
gtid_mode=ON
enforce_gtid_consistency=1
[root@master1 ~]# systemctl restart mysqld
[root@master1 ~]# mysql -uroot -p'Admin.123'
mysql> create user 'rep'@'192.168.28.%' identified by 'Admin.123';
Query OK, 0 rows affected (0.05 sec)

mysql> grant replication slave on *.* to 'rep'@'192.168.28.%';
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> show grants for 'rep'@'192.168.28.%';
+--------------------------------------------------------+
| Grants for [email protected].%                            |
+--------------------------------------------------------+
| GRANT REPLICATION SLAVE ON *.* TO `rep`@`192.168.28.%` |
+--------------------------------------------------------+
1 row in set (0.01 sec)


[root@master1 ~]# mysqldump -uroot -p'Admin.123' -A --single-transaction --source-data=2 --flush-logs > `date +'%F-%T'-all.sql`
[root@master1 ~]# scp ./2023-09-11-02\:10\:19-all.sql [email protected]:/root/

master2——192.168.28.143

[root@master2 ~]# vim /etc/my.cnf
...
log_bin
server-id=1
gtid_mode=ON
enforce_gtid_consistency=1
[root@master2 ~]# systemctl restart mysqld
[root@master2 ~]# ls
2023-09-11-02:10:19-all.sql  anaconda-ks.cfg


[root@master2 ~]# mysql -uroot -p'Admin.123'
mysql> set sql_log_bin=0;
mysql> source /root/2023-09-11-02:10:19-all.sql
mysql> change master to master_host='master1',master_user='rep',master_password='Admin.123',get_master_public_key=1,master_auto_position=1;
mysql> start slave;
mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: master1
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master1-bin.000005
          Read_Master_Log_Pos: 197
               Relay_Log_File: master2-relay-bin.000002
                Relay_Log_Pos: 377
        Relay_Master_Log_File: master1-bin.000005
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
...
mysql> select * from class.stu;
+------+------+
| id   | name |
+------+------+
|    1 | wei  |
+------+------+
1 row in set (0.00 sec)

get_master_public_key=1   在MySQL的主从复制中,主服务器会生成一个公钥(即get_master_public_key),并将其发送给从服务器。从服务器使用该公钥与主服务器建立加密连接,以确保数据传输的安全性。不加此选项会有如下报错

2023-09-10T16:27:42.806971Z 10 [ERROR] [MY-010584] [Repl] Replica I/O for channel '': Error connecting to source 'rep@master1:3306'. This was attempt 2/86400, with a delay of 60 seconds between attempts. Message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection. Error_code: MY-002061

二、配置 master2 为 master1 的主服务器

master2——192.168.28.143

[root@master2 ~]# mysql -uroot -p'Admin.123'
mysql> create user 'per'@'192.168.28.%' identified by 'Admin.123';
Query OK, 0 rows affected (0.00 sec)

mysql> grant replication slave on *.* to 'per'@'192.168.28.%';
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> show grants for 'per'@'192.168.28.%';
+--------------------------------------------------------+
| Grants for [email protected].%                            |
+--------------------------------------------------------+
| GRANT REPLICATION SLAVE ON *.* TO `per`@`192.168.28.%` |
+--------------------------------------------------------+
1 row in set (0.00 sec)

master1——192.168.28.141

[root@master1 ~]# mysql -uroot -p'Admin.123'
mysql> change master to master_host='master2',master_user='per',master_password='Admin.123',get_master_public_key=1,master_auto_position=1;
Query OK, 0 rows affected, 8 warnings (0.00 sec)

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: master2
                  Master_User: per
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master2-bin.000002
          Read_Master_Log_Pos: 663
               Relay_Log_File: master1-relay-bin.000002
                Relay_Log_Pos: 747
        Relay_Master_Log_File: master2-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
...

三、测试双主效果

在master1新增数据,观察master2是否同步

[root@master1 ~]# mysql -uroot -p'Admin.123'
mysql> insert into class.stu values(2,'shu');
Query OK, 1 row affected (0.00 sec)

mysql> select * from class.stu;
+------+------+
| id   | name |
+------+------+
|    1 | wei  |
|    2 | shu  |
+------+------+
2 rows in set (0.00 sec)


[root@master2 ~]# mysql -uroot -p'Admin.123'
mysql> select * from class.stu;
+------+------+
| id   | name |
+------+------+
|    1 | wei  |
|    2 | shu  |
+------+------+
2 rows in set (0.01 sec)

在master2新增数据,观察master1是否同步

[root@master2 ~]# mysql -uroot -p'Admin.123'
mysql> insert into class.stu values(3,'wu');
Query OK, 1 row affected (0.00 sec)

mysql> select * from class.stu;
+------+------+
| id   | name |
+------+------+
|    1 | wei  |
|    2 | shu  |
|    3 | wu   |
+------+------+
3 rows in set (0.00 sec)


[root@master1 ~]# mysql -uroot -p'Admin.123'
mysql> select * from class.stu;
+------+------+
| id   | name |
+------+------+
|    1 | wei  |
|    2 | shu  |
|    3 | wu   |
+------+------+
3 rows in set (0.00 sec)

四、配置双从

master1备份数据,用以两个slave同步数据

[root@master1 ~]# mysqldump -uroot -p'Admin.123' -A --single-transaction --source-data=2 --flush-logs > `date +'%F-%T'-all.sql`
[root@master1 ~]# ls
2023-09-11-03:11:40-all.sql  anaconda-ks.cfg

[root@master1 ~]# scp ./2023-09-11-02\:10\:19-all.sql [email protected]:/root/
[email protected]'s password:
2023-09-11-02:10:19-all.sql                                                                                                                            100% 1255KB  57.5MB/s   00:00
[root@master1 ~]# scp ./2023-09-11-02\:10\:19-all.sql [email protected]:/root/
[email protected]'s password:
2023-09-11-02:10:19-all.sql     

slave1——192.168.28.144

[root@slave1 ~]# ls
2023-09-11-02:10:19-all.sql  anaconda-ks.cfg
[root@slave1 ~]# mysql -uroot -p'Admin.123' < 2023-09-11-02\:10\:19-all.sql

[root@slave1 ~]# vim /etc/my.cnf
...
log_bin
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 -uroot -p'Admin.123'
mysql> change master to master_host='192.168.28.141',master_user='rep',master_password='Admin.123',get_master_public_key=1,master_auto_position=1 for channel '192.168.28.141';
Query OK, 0 rows affected, 8 warnings (0.00 sec)

mysql> change master to master_host='192.168.28.143',master_user='per',master_password='Admin.123',get_master_public_key=1,master_auto_position=1 for channel '192.168.28.143';
Query OK, 0 rows affected, 8 warnings (0.00 sec)

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 192.168.28.141
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master1-bin.000006
          Read_Master_Log_Pos: 237
               Relay_Log_File: slave1-relay-bin-192@002e168@[email protected]
                Relay_Log_Pos: 457
        Relay_Master_Log_File: master1-bin.000006
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
...
*************************** 2. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 192.168.28.143
                  Master_User: per
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master2-bin.000002
          Read_Master_Log_Pos: 1235
               Relay_Log_File: slave1-relay-bin-192@002e168@[email protected]
                Relay_Log_Pos: 1455
        Relay_Master_Log_File: master2-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

mysql> select * from class.stu;
+------+------+
| id   | name |
+------+------+
|    1 | wei  |
|    2 | shu  |
|    3 | wu   |
+------+------+
3 rows in set (0.00 sec)

slave2——192.168.28.145

[root@slave2 ~]# ls
2023-09-11-02:10:19-all.sql  anaconda-ks.cfg
[root@slave2 ~]# mysql -uroot -p'Admin.123' < 2023-09-11-02\:10\:19-all.sql

[root@slave2 ~]# vim /etc/my.cnf
...
log_bin
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 -uroot -p'Admin.123'
mysql> change master to master_host='192.168.28.141',master_user='rep',master_password='Admin.123',get_master_public_key=1,master_auto_position=1 for channel '192.168.28.141';
Query OK, 0 rows affected, 8 warnings (0.00 sec)

mysql> change master to master_host='192.168.28.143',master_user='per',master_password='Admin.123',get_master_public_key=1,master_auto_position=1 for channel '192.168.28.143';
Query OK, 0 rows affected, 8 warnings (0.00 sec)

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 192.168.28.141
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master1-bin.000006
          Read_Master_Log_Pos: 237
               Relay_Log_File: slave2-relay-bin-192@002e168@[email protected]
                Relay_Log_Pos: 457
        Relay_Master_Log_File: master1-bin.000006
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
...
*************************** 2. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 192.168.28.143
                  Master_User: per
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master2-bin.000002
          Read_Master_Log_Pos: 1235
               Relay_Log_File: slave2-relay-bin-192@002e168@[email protected]
                Relay_Log_Pos: 1455
        Relay_Master_Log_File: master2-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

mysql> select * from class.stu;
+------+------+
| id   | name |
+------+------+
|    1 | wei  |
|    2 | shu  |
|    3 | wu   |
+------+------+
3 rows in set (0.00 sec)

master-info-repository   是MySQL主从复制配置中的选项,用于指定主服务器信息存储的方式。它可以在配置文件或表中存储主服务器的信息。

  • 当master-info-repository的值为FILE时,主服务器的信息会被保存在从服务器数据目录下的master.info和relay-log.info两个文件中。
  • 当master-info-repository的值为TABLE时,主服务器的信息会被保存在MySQL数据库的master_slave_info表中。

relay-log-info-repository   是MySQL主从复制中的一个参数,用于指定relay log信息存储的方式。

  • 当relay-log-info-repository的值为TABLE时,从服务器上的relay log信息会被保存在MySQL数据库的slave_relay_log_info表中,以供从服务器在处理复制过程中使用。
  • relay-log-info-repository的默认值取决于存储引擎。在InnoDB存储引擎下,relay-log-info-repository的默认值是TABLE。

经测试,当修改master1或master2数据时,其余三台设均能实现数据同步。

你可能感兴趣的:(运维工具,#,MySQL,mysql,数据库,linux,运维)