MySQL的仿制形式
异步仿制
MySQL的仿制方法默许是异步的,主从仿制触及三个线程
- master I/O master I/O线程担任写入Binlog,并将履行成果返给客户端,至于Binlog有没有被IO线程读取,读取后有没有重放,重放有没有成功,它是不关心的。
- slave I/O线程 担任将读取master的Binlog并写入slave的relay log(中继日志)
- slave sql线程 在slave重放relay log中的event,MySQL5.6以后支撑并行仿制,所谓并行仿制,指的是从库敞开多个SQL线程,并行读取relay log中不同库的日志,然后并行重放不同库的日志,这是库等级的并行。而MySQL 5.7版别对并行仿制进一步改善,现已支撑“真正”的并行仿制功能,是基于组提交的并行仿制,一个组提交的业务都是能够并行回放,官方称为enhanced multi-threaded slave(简称MTS),仿制推迟问题现已得到了极大的改善。
这种形式在高并发的情况下,master只担任写Binlog和回来成果,至于Binlog有没有被读取和重放,它是不关心的,那么这就或许就发生主从推迟的问题。或许master宕机后,slave晋级为master,但是binlog未履行完毕,就会导致数据不一致。
这里讲一个小技巧,为了削减主从推迟的问题,主库和备库的硬件功能尽或许保持一致,假如主备硬件距离比较大,从主从推迟的角度上看,应该在功能更好的机器上面装置备库。假如给主库用更好的硬件,那推迟只会越来越大。
半同步仿制
为了解决异步存在的问题,MySQL5.5版别推出半同步仿制,在master履行完毕后,commit之前,slave的io进程开始把Binlog写入到relaylog中,写完之后,反馈给master,master收到任何一个slave的反馈后,履行commit并回来成果给客户端。半同步的机制削减了主从数据不同步的问题,但是也牺牲了一部分主库的功能,比异步仿制至少多了一个tcp的往返时刻。
假如在更新期间,主从库发生了网络毛病或许从库宕机,那么此刻主库在业务提交后会等候10秒(默许值),假如10秒内仍是不能联系到该从库,就会抛弃更新该从库,并向用户回来数据。这时主从库就会康复到默许的异步仿制状况。
同步仿制【不推荐】
全同步仿制(full sync replication)是指当主库履行完一个业务后,需求确保一切的从库都履行了该业务才回来给客户端。由于需求等候一切的从库都履行完该业务才干回来,所以全同步仿制的功能较差。 MySQL本身不支撑同步仿制,需求用到第三方东西如DRBD(sync形式)等完成同步仿制,严格来说,把半同步仿制技术默许(或人为)全部应用到一切从库上也算是全同步仿制。
MGR组仿制
MGR(MySQL GroupReplication)是MySQL 5.7.17提出的,MGR既能够很好的确保数据一致性又能够主动切换,具有毛病检测功能、支撑多节点写入.MGR (MySQL Group Replication)是MySQL自带的一个插件,能够灵活布置。MySQL MGR集群是多个MySQL Server节点一起组成的分布式集群,每个Server都有完整的副本,它是基于ROW格局的二进制日志文件和GTID特性。架构主要是APIs层、组件层、仿制协议模块层和GCSAPI+Paxos引擎层构成。
MGR的解决的问题
- 高可用性:由于数据在多个服务器之间仿制,因而即便某个服务器呈现毛病,也不会影响到全体的服务。
- 数据一致性:MGR运用了一种称为“多数派”或“半数以上”的战略来确保数据的一致性。只要当大多数服务器都确认了一次操作,这次操作才会被视为有效。
- 负载均衡:MGR答应你将读取操作在多个服务器之间分配,然后完成负载均衡。
MGR带来的问题
- 写入功能:由于需求在多个服务器之间仿制数据,因而写入操作或许会比在单个服务器上履行慢。
- 网络推迟:假如服务器之间的网络连接不稳定或许推迟高,或许会影响到MGR的功能和可靠性。
- 办理杂乱性:办理和保护一个MGR集群或许会比办理单个服务器更杂乱。
如何削减主从推迟的问题
- 查主库 这是咱们现在运用的方法,当要求数据一致性的时分,先写主库,再读主库,比方刺进订单表之后要立刻查询订单的信息。
- 分库 原来一个库的并发是400/s,咱们把一个库拆分为4个库后,每个库的并发就能够均匀到100/s(这个拆分,不是让你把表均匀分了,而是要根据业务量拆分,使得每个库都能得到合理的访问量)
- 硬件设备尽或许保持一致,网络推迟短
- 敞开并行仿制。发动多个SQL线程处理relaylog
动手完成半同步和MGR
半同步仿制的装置
- 检查动态加载是否为true 履行指令
show variables like "have_dynamic_loading";
- 装置插件,在master履行
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
,在slave履行INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
- 如需卸载(便是封闭半同步),则别离履行
UNINSTALL PLUGIN rpl_semi_sync_master;
和UNINSTALL PLUGIN rpl_semi_sync_slave;
- 履行
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';
检查插件是否启用 - MySQL默许是异步的,咱们经过指令
SET GLOBAL rpl_semi_sync_master_enabled = 1;
敞开半同步,在slave履行SET GLOBAL rpl_semi_sync_slave_enabled = 1;
- 也能够装备在my.cnf文件中
#master装备
plugin-load=rpl_semi_sync_master=semisync_master.so
rpl_semi_sync_master_enabled=1
# slave装备
plugin-load=rpl_semi_sync_slave=semisync_slave.so
rpl_semi_sync_slave_enabled=1
- 重新发动slave的IO thread
mysql> STOP SLAVE IO_THREAD;
Query OK, 0 rows affected, 1 warning (0.03 sec)
mysql> START SLAVE IO_THREAD;
Query OK, 0 rows affected, 1 warning (0.01 sec)
- 检查半同步的状况,在master履行
show status like 'Rpl_semi_sync_master_status';
,在slave履行show status like 'Rpl_semi_sync_slave_status';
- 咱们前面说过,超过10s的话半同步就会降级为异步,那么这个10s哪来的呢?咱们履行
show variables like "rpl_semi_sync_master_timeout";
来看一下 - 咱们刺进一条记载到user表看一下
- 接下来咱们看看,假如停了slave,master会不会降级为异步。从库履行指令
stop slave
;主库刺进数据,发现履行刺进句子后一直等候,10s后回来成果,检查主库的半同步状况show status like 'Rpl_semi_sync_master_status';
和从库的状况show status like 'Rpl_semi_sync_slave_status';
现已封闭 - 在slave履行
start slave;
半同步状况将会再次敞开;
其他参数说明
-
咱们经过
show variables like '%Rpl%';
和show status like '%Rpl_semi%';
能够看到其他的参数 -
rpl_semi_sync_master_wait_for_slave_count: MySQL 5.7.3引入的,该变量设置主需求等候多少个slave应对,才干回来给客户端,默许为1。
MGR的相关装备
- 以下装备是基于MySQL8.0 上篇文章咱们运用docker创立了两个MySQL服务,那么在这个案例中,咱们仍是运用docker快速发动三个服务,在发动前,咱们先来看一下需求装备哪些项,咱们拿一个装备文件作为参阅
# 指定了服务器的唯一标识符,用于仿制或群组仿制。每个服务器有必要有一个不同的server_id值
server_id=1
# 启用了全局业务标识符(GTID)形式,这是一种仿制形式,能够盯梢每个业务的履行情况,而不需求运用二进制日志文件名和方位
gtid_mode=ON
# 强制GTID形式的一致性,即只答应那些能够安全地运用GTID仿制的句子履行
enforce_gtid_consistency=ON
# 禁用了二进制日志的校验和功能,即不在二进制日志事情中增加额定的数据来验证事情的完整性
binlog_checksum=NONE
# 启用了二进制日志,并指定了二进制日志文件的根本称号为binlog
log_bin=binlog
# 使得从服务器在接收到主服务器的更新后,也将这些更新记载到自己的二进制日志中,这关于链式仿制或备份从服务器很有用
log_slave_updates=ON
# 指定了二进制日志的格局为行格局,即记载每个被修正的行的变化,而不是记载履行的句子
binlog_format=ROW
# 指定了从服务器存储主服务器信息(如主服务器的主机名、端口号、用户名、密码等)的方位为一个表(mysql.slave_master_info),而不是一个文件(master.info)
master_info_repository=TABLE
# 指定了从服务器存储中继日志信息(如当时正在履行的中继日志文件名和方位等)的方位为一个表(mysql.slave_relay_log_info),而不是一个文件(relay-log.info)
relay_log_info_repository=TABLE
# 指定了业务写集提取算法为XXHASH64,这是一种快速的哈希算法,用于生成每个业务写集的唯一标识符,以便在群组仿制中检测和防止抵触
transaction_write_set_extraction=XXHASH64
# 指定了群组仿制中的群组称号,它是一个128位的无符号整数,用16进制表示,用于标识一个仿制群组。一切参加群组仿制的服务器有必要运用相同的群组称号
loose-group_replication_group_name="aadaaaaa-adda-adda-aaaa-aaaaaaddaaaa"
# 指定了服务器发动时是否主动发动群组仿制插件。假如设置为OFF,则需求手动履行START GROUP_REPLICATION句子来发动群组仿制
loose-group_replication_start_on_boot=OFF
# 指定了本地服务器在群组仿制中运用的地址,包括IP地址和端口号。这个地址用于与其他群组成员通讯
loose-group_replication_local_address= "172.17.0.2:13308"
# 指定了一组种子地址,用于在发动群组仿制时发现其他群组成员。这些地址能够是本地服务器或远程服务器的地址
loose-group_replication_group_seeds= "172.17.0.2:13308,172.17.0.3:13309,172.17.0.4:13310"
# 指定了是否将本地服务器作为引导服务器,用于创立一个新的群组或康复一个已有的群组。只要在没有其他可用的群组成员时,才需求设置这个参数为ON
loose-group_replication_bootstrap_group=OFF;
- 咱们创立一个专门的网络,用来连接各个容器
$ docker network create mysql_mgr
$ docker network ls
- 咱们需求MySQL对外服务的端口,还需求群组仿制运用的端口,那么咱们改一下咱们的docker发动指令,咱们先来发动一个mysql-c,创立目录mysqlc ,进入目录并履行
docker run -d --name mysql-c -p 23308:3306 \
--net=mysql_mgr \
-v $(pwd)/conf:/etc/mysql/conf.d \
-v $(pwd)/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
mysql
- 创立目录mysqld并履行
docker run -d --name mysql-d -p 23309:3306 \
--net=mysql_mgr \
-v $(pwd)/conf:/etc/mysql/conf.d \
-v $(pwd)/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
mysql
- 创立目录mysqle并履行
docker run -d --name mysql-e -p 23310:3306 \
--net=mysql_mgr \
-v $(pwd)/conf:/etc/mysql/conf.d \
-v $(pwd)/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
mysql
- 运用下面指令找到容器对应的ip
$ docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mysql-c
/mysql-c - 172.17.0.2
- 咱们参照上面的装备文件装备自己my.cnf,并重启docker容器,假如你忘记了my.cnf的目录,能够运用
mysql --help | grep "my.cnf"
检查my.cnf的目录
[mysqld]
# 指定了服务器的唯一标识符,用于仿制或群组仿制。每个服务器有必要有一个不同的server_id值
server_id=3
# 启用了全局业务标识符(GTID)形式,这是一种仿制形式,能够盯梢每个业务的履行情况,而不需求运用二进制日志文件名和方位
gtid_mode=ON
# 强制GTID形式的一致性,即只答应那些能够安全地运用GTID仿制的句子履行
enforce_gtid_consistency=ON
# 禁用了二进制日志的校验和功能,即不在二进制日志事情中增加额定的数据来验证事情的完整性
binlog_checksum=NONE
# 启用了二进制日志,并指定了二进制日志文件的根本称号为binlog
log_bin=binlog
# 使得从服务器在接收到主服务器的更新后,也将这些更新记载到自己的二进制日志中,这关于链式仿制或备份从服务器很有用
log_slave_updates=ON
# 指定了二进制日志的格局为行格局,即记载每个被修正的行的变化,而不是记载履行的句子
binlog_format=ROW
# 指定了从服务器存储主服务器信息(如主服务器的主机名、端口号、用户名、密码等)的方位为一个表(mysql.slave_master_info),而不是一个文件(master.info)
master_info_repository=TABLE
# 指定了从服务器存储中继日志信息(如当时正在履行的中继日志文件名和方位等)的方位为一个表(mysql.slave_relay_log_info),而不是一个文件(relay-log.info)
relay_log_info_repository=TABLE
# 指定了业务写集提取算法为XXHASH64,这是一种快速的哈希算法,用于生成每个业务写集的唯一标识符,以便在群组仿制中检测和防止抵触
transaction_write_set_extraction=XXHASH64
# 指定了群组仿制中的群组称号,它是一个128位的无符号整数,用16进制表示,用于标识一个仿制群组。一切参加群组仿制的服务器有必要运用相同的群组称号
loose-group_replication_group_name="aadaaaaa-adda-adda-aaaa-aaaaaaddaaaa"
# 指定了服务器发动时是否主动发动群组仿制插件。假如设置为OFF,则需求手动履行START GROUP_REPLICATION句子来发动群组仿制
loose-group_replication_start_on_boot=OFF
# 指定了本地服务器在群组仿制中运用的地址,包括IP地址和端口号。这个地址用于与其他群组成员通讯
loose-group_replication_local_address= "172.21.0.4:13308"
# 指定了一组种子地址,用于在发动群组仿制时发现其他群组成员。这些地址能够是本地服务器或远程服务器的地址
loose-group_replication_group_seeds= "172.21.0.2:13306,172.21.0.3:13307,172.21.0.4:13308"
# 指定了是否将本地服务器作为引导服务器,用于创立一个新的群组或康复一个已有的群组。只要在没有其他可用的群组成员时,才需求设置这个参数为ON
loose-group_replication_bootstrap_group=OFF;
# 修正MySQL8的验证插件为mysql_native_password
default_authentication_plugin=mysql_native_password
- 进入容器履行以下指令(每个机器都要操作)
SET SQL_LOG_BIN=0;
CREATE USER mgruser@'%' IDENTIFIED BY 'mgruser';
GRANT REPLICATION SLAVE ON *.* TO mgruser@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;
CHANGE MASTER TO MASTER_USER='mgruser', MASTER_PASSWORD='mgruser' FOR CHANNEL 'group_replication_recovery';
- 下载插件(每个机器都要操作)
install PLUGIN group_replication SONAME 'group_replication.so';
- 经过
show plugins
检查插件是否装置成功 - 至此,三台MySQL服务器装备完毕,咱们现在选择一台(即单主形式)作为master并履行命
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
SELECT * FROM performance_schema.replication_group_members;
- 由于是mysql8验证方法的问题,咱们需求在两台备库上面履行
mysql -umgruser -pmgruser -h172.21.0.2 --get-server-public-key
- 在备库履行
START GROUP_REPLICATION;
- 查询集群的状况
SELECT * FROM performance_schema.replication_group_members;
,全部是online才算成功,中心假如有发动过错,能够经过docker logs container_name
来检查过错日志 - 装备成功后,咱们在master新建一个数据库看一下
create database mgr;
,咱们看到从库现已同步过去了; - 咱们停掉主库看一下
stop group_replication;
主库和备库的状况,咱们发现主库停掉后,会有一个备库晋级成主库持续提供服务
- 咱们在master创立一个表,刺进几条记载
use mgr;
CREATE TABLE `user` (
`id` bigint NOT NULL ,
`account` varchar(30) NOT NULL ,
`name` varchar(50) NOT NULL ,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `UN_ACCOUNT` (`account`) USING BTREE
)
INSERT INTO user VALUES (1, 'zhangsan', '张三');
INSERT INTO user VALUES (2, 'lisi', '李四');
- 在备库上也刺进一条看一下作用,刺进失利,并且提示是只读的,并且主库刺进的数据也读到了
参阅文档
- 相关参阅
- 相关参阅
- 相关参阅
- 参阅文章