mysql主从复制 | 级联方式复制 | 并行复制 | 半同步复制 | 全同步

两种模式

一主两从

      server1

       /     \

server2  server3

级联式

server1<----server2<------server3

注意:

去中心化server3找server2,server2找server1  -------级联,这样降低了server1的负载

配置mysql是,很多问题直接看报错日志就可以解决!!!!!

主从复制是单向的,不能在从机直接操作数据库写数据

主从复制的基础是在底层数据一致上才能搭建,如果不一致,一定要先同步数据在slave上

///////////////////////保证数据一致性,导入数据库////////////////////////////////////////////////////////////

1,主:mysqldump -p test > test.sql  默认会复制gtid信息

注意:mysqldump有个bug,如果在从机上存在和要备份名字一样的表,那么回删除这个表,也就是从机数据会丢失

2,scp test.sql server从机

在导入之前需要修改test.sql(要创建这个库,如果已经存在就不用创建了,还要使用这个库,和下面的sql语句衔接,从sql语句可以看到,会删除userlist 如果它存在)

3,mysq -p < test.sql

此时可以登录查看已经出现了test库和userlist表

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

(/etc/my.cnf里面参数的下划线和短横线没有什么区别)

一,基于gtid的数据库级联主从复制:
server1 < server2 < server3

server2里面要写log-slave-updates,如果server3后面还有节点,那么在server2上面也需要写log-slave-updates,而且需要在server3中认server2主 ,以此类推,其实配置时可以认为就是一主一从,级联配置同server1-server2

1,配置文件:

server2如下

server3如下

2,server2上授权(serevr2是server3的master)

3,授权之后可以远程登录测试一下用户

4,server3上配置server2为master,启动slave,如果之前是slave,必须要先stop slave;

配置完成!!!可以在server1上写入数据,如果server3可以看到,那么server2一定可以看见,因为server3就是从server2那获取的数据。

二,并行复制

多线程,当主库写入很频繁时,从库复制要等很久

1,只在slave中配置 server2,server3,主库不变

vim /etc/my.cnf

slave-parallel-type=LOGICAL_CLOCK

slave-parallel-workers=16不要设置为1,那样反而效率很低

master_info_repository=TABLE

relay_log_info_repository=TABLE

relay_log_recovery=ON

等于TABLE 相当于直接写在数据库里面,避免重复记录在/etc/lib/mysqlmaster.info里面,一直刷磁盘

2,重启server2,sever3的mysql服务

3,此时查看进程

********************************************************

判断延迟

show slave status

三个值

Read_Master_Log_Pos:

Exec_Master_Log_Pos:这两个pos号相等

Seconds_Behind_Master:这个值为0 那么可以判断无延迟

********************************************************

***************************延迟服务器*****************

1,避免误操作delete,此时还可以从延迟服务器中挽救

2,测延迟对业务的影响,最大多大的延迟会影响到业务

**********************************************************

普通的replication,即mysql的异步复制,依靠mysql二进制日志也即binary log进行数据复制。比如两台机器,一台主机(master),另外一台是从机(slave)。

  1. 正常的复制为:事务一(t1)写入binlog buffer;dumper 线程通知slave有新的事务t1;binlog buffer 进行checkpoint;slave的io线程接收到t1并写入到自己的的relay log;slave的sql线程写入到本地数据库。 这时,master和slave都能看到这条新的事务,即使master挂了,slave可以提升为新的master。
  2. 异常的复制为:事务一(t1)写入binlog buffer;dumper 线程通知slave有新的事务t1;binlog buffer 进行checkpoint;slave因为网络不稳定,一直没有收到t1;master 挂掉,slave提升为新的master,t1丢失。
  3. 很大的问题是:主机和从机事务更新的不同步,就算是没有网络或者其他系统的异常,当业务并发上来时,slave因为要顺序执行master批量事务,导致很大的延迟。

为了弥补以上几种场景的不足,mysql从5.5开始推出了半同步。即在master的dumper线程通知slave后,增加了一个ack,即是否成功收到t1的标志码。也就是dumper线程除了发送t1到slave,还承担了接收slave的ack工作。如果出现异常,没有收到ack,那么将自动降级为普通的复制,直到异常修复。

半同步带来的新问题

  1. 如果异常发生,会降级为普通的复制。 那么从机出现数据不一致的几率会减少,并不是完全消失。
  2. 主机dumper线程承担的工作变多了,这样显然会降低整个数据库的性能。
  3. 在MySQL 5.5和5.6使用after_commit的模式下, 即如果slave 没有收到事务,也就是还没有写入到relay log 之前,网络出现异常或者不稳定,此时刚好master挂了,系统切换到从机,两边的数据就会出现不一致。 在此情况下,slave会少一个事务的数据。

随着MySQL 5.7版本的发布,半同步复制技术升级为全新的Loss-less Semi-Synchronous Replication架构,其成熟度、数据一致性与执行效率得到显著的提升。

三,半同步

1,如果是节耦级联式那么server2作为master和slave都要安装插件之类的,使能写在/etc/my.cnf可以永久实现,而且必须写在[mysqld]中,延时可以不用写

show plugins;查看插件

2,只要是主机server1,servre2配置为:

install pluginstall plugin rpl_semi_sync_master soname 'semisync_master.so';

in rpl_semi_sync_master soname 'semisync_master.so';

set global rpl_semi_sync_master_enabled=ON; 

只要是从机server2,server3配置为:

install plugin rpl_semi_sync_slave soname 'semisync_slave.so';

set global rpl_semi_sync_slave_enabled=ON;

3,从机半同步一定要stop/start slave io_thread才会生效,否则查看show variables like 'rpl_semi_sync% 状态是OFF'

所以级联式应该是这样

server1

server2

server3

安装插件,然后

4,查看变量

server2上面既有master又有slave的信息

延迟10000ms=10s

5,查看状态,每行都是什么意思

测试

server2或者server3关闭 stop slave io_thread;然后master插入数据,会有10s的延迟,并且slave看不到同步数据,打开start slave io_thread才可以看到,而且级联中只要有slave停止了io进程,那么整个都不会同步数据

重点!!!!

异步无法保证数据的一致性

半同步在生产中设置异步延迟为无穷大oo,实验中我们没有设置,默认为10s,这样stop slave io_thread就相当于slave端有问题了,此时会去找异步方式,但是异步方式延迟是无穷大,slave端永远同步不了数据,无法返回给master一个ack,所以master也没办法把数据从内存记入mysql_bin写入磁盘,但是这样会导致master端一致处于等待的状态,也就是说master端业务无法正常允许,客户端无法向数据库写入数据,这也是和异步不一样的,异步不用等ack,我不管你slave端的状态如何,在你返回一个ack之前,我已经把buffer里面的数据sync写入内存,这也就是为什么异步无法保证数据的一致性的原因

MySQL 5.7 引入了新的变量slave-parallel-type,其可以配置的值有: 1. DATABASE (5.7之前默认值),基于库的并行复制方式; 2. LOGICAL_CLOCK (5.7新增值),基于组提交的并行复制方式; MySQL 5.6版本也支持所谓的并行复制,但是其并行只是基于DATABASE的,也就是基于库的。如果用户的MySQL数据库实例中存在多个DATABASE ,对于从机复制的速度的确可以有比较大的帮助,如果用户实例仅有一个库,那么就无法实现并行回放,甚至性能会比原来的单线程更差。 MySQL5.7中增加了一种新的并行模式:为同时进入COMMIT阶段的事务分配相同的序列号,这些拥有相同序列号的事务在备库是可以并发执行的。 MySQL 5.7真正实现的并行复制,这其中最为主要的原因就是slave服务器的回放与主机是一致的即master服务器上是怎么并行执行的slave上就怎样进行并行回放。不再有库的并行复制限制,对于二进制日志格式也无特殊的要求(基于库的并行复制也没有要求)。

四,组复制(全同步)

每个都是master,都可以读写

1,停掉所有的mysql

2,删除/var/lib/mysql的所有

首节点配置如下server1

1,

可以修改/etc/init.d/mysqld

2,修改配置文件

https://dev.mysql.com/doc/refman/5.7/en/group-replication-configuring-instances.html  

server_id=1

gtid_mode=ON

enforce_gtid_consistency=ON

master_info_repository=TABLE

relay_log_info_repository=TABLE

binlog_checksum=NONE

log_slave_updates=ON

log_bin=binlog

binlog_format=ROW



transaction_write_set_extraction=XXHASH64

loose-group_replication_group_name="7552e307-9c7c-11e8-af0d-525400f07421"

loose-group_replication_start_on_boot=off

loose-group_replication_local_address= "172.25.28.1:24901"

loose-group_replication_group_seeds= "172.25.28.1:24901,172.25.28.2:24901,172.25.28.3:24901"

loose-group_replication_bootstrap_group=off

loose-group_replication_single_primary_mode=off

loose-group_replication_enforce_update_everywhere_checks=on

(loose的意思就是初始化的时候不检查,虽然这些模块在启动mysql的时候没有,但是后续会添加,防止无法启动)

mysql> select uuid();  这个随意获取,这就是loose-group_replication_group_name

+--------------------------------------+

| uuid()                               |

+--------------------------------------+

| 7440de46-9c7c-11e8-af0d-525400f07421 |

+--------------------------------------+

1 row in set (0.00 sec)

3,启动服务

4,获取密码,注意里面也记录了之前的密码,要看时间

grep password /var/log/mysqld.log

5,如果没有安全初始化直接登录使用数据库时,它会让你修改密码

alter user root@localhost identified by 'Zming=1998';

6,配置

如果没有在my.cnf里面设置ip白名单执行START GROUP_REPLICATION;

会出错,这里我们先设置全局变量,结束后在my.cnf添加

7,建立库,表

配置完之后要在配置文件里面写上白名单,之前设定的全局变量重启之后就不生效了

/etc/my.cf追加

loose-group_replication_ip_whitelist="172.25.28.0/24,127.0.0.1/8"

server2

1,先停止服务,删除/var/lib//mysql所有数据

2,修改配置文件,两处和server1不一样

server_id=2                                             ###

gtid_mode=ON

enforce_gtid_consistency=ON

master_info_repository=TABLE

relay_log_info_repository=TABLE

binlog_checksum=NONE

log_slave_updates=ON

log_bin=binlog

binlog_format=ROW



transaction_write_set_extraction=XXHASH64

loose-group_replication_group_name="7552e307-9c7c-11e8-af0d-525400f07421"

loose-group_replication_start_on_boot=off

loose-group_replication_local_address= "172.25.28.2:24901"       ###

loose-group_replication_group_seeds= "172.25.28.1:24901,172.25.28.2:24901,172.25.28.3:24901"

loose-group_replication_bootstrap_group=off

loose-group_replication_single_primary_mode=off

loose-group_replication_enforce_update_everywhere_checks=on

loose-group_replication_ip_whitelist="172.25.28.0/24,127.0.0.1/8"

3,启动服务

4,登录修改密码,配置服务

mysql> show databases;

ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.

mysql> alter user root@localhost identified by 'Zming=1998';

Query OK, 0 rows affected (0.07 sec)

mysql> SET SQL_LOG_BIN=0;

Query OK, 0 rows affected (0.00 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%' IDENTIFIED BY 'Zming=1998';

Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> reset master;

Query OK, 0 rows affected (0.13 sec)

mysql> SET SQL_LOG_BIN=1;

Query OK, 0 rows affected (0.00 sec)

mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='Zming=1998' FOR CHANNEL 'group_replication_recovery';

Query OK, 0 rows affected, 2 warnings (0.18 sec)

mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';

mysql> START GROUP_REPLICATION;

Query OK, 0 rows affected (6.01 sec)

这里和server1首节点的配置有点不一样,不用SET GLOBAL group_replication_bootstrap_group=ON,SET GLOBAL group_replication_bootstrap_group=OFF

5,查看

mysql> select * from test.t1;

+----+------+

| c1 | c2   |

+----+------+

|  1 | Luis |

+----+------+

1 row in set (0.00 sec)

仿照server2添加server3

1,先停止服务,删除/var/lib//mysql所有数据

2,修改配置文件,两处和server1不一样

server_id=3                                           ###

gtid_mode=ON

enforce_gtid_consistency=ON

master_info_repository=TABLE

relay_log_info_repository=TABLE

binlog_checksum=NONE

log_slave_updates=ON

log_bin=binlog

binlog_format=ROW



transaction_write_set_extraction=XXHASH64

loose-group_replication_group_name="7552e307-9c7c-11e8-af0d-525400f07421"

loose-group_replication_start_on_boot=off

loose-group_replication_local_address= "172.25.28.3:24901"       ###

loose-group_replication_group_seeds= "172.25.28.1:24901,172.25.28.2:24901,172.25.28.3:24901"

loose-group_replication_bootstrap_group=off

loose-group_replication_single_primary_mode=off

loose-group_replication_enforce_update_everywhere_checks=on

loose-group_replication_ip_whitelist="172.25.28.0/24,127.0.0.1/8"

3,重启服务

4,登录修改密码,配置服务

mysql> show databases;

ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.

mysql> alter user root@localhost identified by 'Zming=1998';

Query OK, 0 rows affected (0.07 sec)

mysql> SET SQL_LOG_BIN=0;

Query OK, 0 rows affected (0.00 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%' IDENTIFIED BY 'Zming=1998';

Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> reset master;

Query OK, 0 rows affected (0.18 sec)

mysql> SET SQL_LOG_BIN=1;

Query OK, 0 rows affected (0.00 sec)

mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='Zming=1998' FOR CHANNEL 'group_replication_recovery';

Query OK, 0 rows affected, 2 warnings (0.34 sec)

mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';

Query OK, 0 rows affected (0.17 sec)

mysql> START GROUP_REPLICATION;

Query OK, 0 rows affected (2.91 sec)

mysql> SELECT * FROM performance_schema.replication_group_members;

+---------------------------+--------------------------------------+-------------+-------------+--------------+

| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |

+---------------------------+--------------------------------------+-------------+-------------+--------------+

| group_replication_applier | 1fd24e68-9c83-11e8-9cf5-5254002c0a1d | server2     |        3306 | ONLINE       |

| group_replication_applier | 41f9478b-9c7d-11e8-914d-525400d4f7b9 | server1     |        3306 | ONLINE       |

| group_replication_applier | 4af67249-9c86-11e8-8f8c-525400f07421 | server3     |        3306 | ONLINE       |

+---------------------------+--------------------------------------+-------------+-------------+--------------+

3 rows in set (0.00 sec)

注意:1,这三个节点都必须ONLINE

2,初始节点要做开启SET GLOBAL group_replication_bootstrap_group=ON,关闭SET GLOBAL group_replication_bootstrap_group=OFF之后节点的就不用了

3,同样的数据是查不进去的,有主键

mysql> INSERT INTO test.t1 VALUES (1, 'Luis');

ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

mysql> select * from test.t1;

+----+------+

| c1 | c2   |

+----+------+

|  1 | Luis |

+----+------+

1 row in set (0.00 sec)

测试:

在server2上添加数据

mysql> INSERT INTO test.t1 VALUES (2, 'Luis');

Query OK, 1 row affected (0.33 sec)

在server1,3上都可以看见

mysql>  select * from test.t1;

+----+------+

| c1 | c2   |

+----+------+

|  1 | Luis |

|  2 | Luis |

+----+------+

2 rows in set (0.00 sec)

注意:三个节点最多允许down一个,否则构成不了集群

猜你喜欢

转载自blog.csdn.net/ha_weii/article/details/81571348