两种模式
一主两从
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)。
为了弥补以上几种场景的不足,mysql从5.5开始推出了半同步。即在master的dumper线程通知slave后,增加了一个ack,即是否成功收到t1的标志码。也就是dumper线程除了发送t1到slave,还承担了接收slave的ack工作。如果出现异常,没有收到ack,那么将自动降级为普通的复制,直到异常修复。
半同步带来的新问题:
随着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';
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一个,否则构成不了集群