目录
1、mysql主从复制用途
2、主从部署必要条件
3、主从模式实现原理
3.1、主从复制
3.2、半同步复制
3.3、并行复制
3.3.1、MySQL5.6并行复制原理
3.3.2、MySQL5.7并行复制原理
3.3.3、MySQL5.8并行复制
3.3.4、并行复制配置与调优
3.3.5、并行复制监控
3.4、读写分离
3.4.1、主从同步延迟
3.4.2、读写分配机制
4、主从模式实战
4.1、主从复制
4.1.1、修改主库my.ini配置文件
4.1.2、在主库配置slave访问master的用户的ip权限
4.1.3、修改从库my.ini配置文件
4.1.4、从库配置关联主库
4.2、半同步复制
4.2.1、主库安装半同步复制插件semi
4.2.2、修改semi相关配置
4.2.3、从库安装半同步复制插件semi
4.3、并行复制
4.3.1、主库设置基于组提交的并行复制
4.3.2、从库设置并行复制(也可以直接在my.ini文件中进行配置)
数据可以从一个MySQL数据库主节点复制到多个从节点(异步复制)。
主从复制主要有以下三大步骤:
以上三个步骤,分别涉及主库的BinlogDump Thread和从库的IO Thread、SQL Thread,其中:
在主库的binlogDump Thread将binlog信息推送给从库的IO Thread后,从库进行异步处理,存在数据延迟的情况。
MySQL让Master在某一个时间点等待Slave节点的 ACK消息,接收到ACK消息后才进行事务提交,可降低数据丢失的问题。
目的是解决从库复制延迟的问题。
从库在复制主库数据时,主要是依赖IO Thread和SQL Thread两个线程,而这两个都是单线程,所以存在延迟问题。我们可通过使用SQL Thread多线程来加强从库复制,减少从库复制延迟。
基于数据库的并行复制,每个数据库使用一个单独的SQL Thread。但无法解决单库多表的从库复制延迟问题。也无法处理事务并行处理的执行顺序。
如下所示:事务T1、T2、T3,分别操作数据库DB1、DB2、DB3,三个事务互不影响,因此在Mysql5.6就会有三个SQL Thread线程,分别执行三个事务的写入操作。
InnoDb事务提交为两阶段提交:一个阶段是prepare,一个阶段是commit。
基于组提交的并行复制,多个事务如果能同时提交成功,说明这些事务是没有冲突的,可以并行提交,那么就把这些事务分为一组,在主库上的二进制日志中添加组提交信息。在从库上就可以并行复制了。
MySQL 5.7的并行复制基于一个前提,即所有已经处于prepare阶段的事务,都是可以并行提交的。
MySQL5.7配置复制方式:
变量slave-parallel-type,其可以配置的值有:DATABASE(默认值,基于库的并行复制方式)、LOGICAL_CLOCK(基于组提交的并行复制方式)
从库复制时如何从binlog日志中,判断哪些事务是可以并行复制的?
last_committed表示事务提交时,上次事务提交的编号。相同的为同一组,可以进行并行复制。
基于write-set的并行复制,并行颗粒度为行记录。MySQL会有一个集合变量来存储事务修改的记录信息(主键哈希值),所有已经提交的事务所修改的主键值经过hash后都会与那个变量的集合进行对比,来判断该行是否与其冲突,并以此来确定依赖关系,没有冲突即可并行。这样的粒度,就到了row级别了,此时并行的粒度更加精细,并行的速度会更快。
用于控制集合变量的大小。
用于控制binlog文件中事务之间的依赖关系,即last_committed值。
COMMIT_ORDERE: 基于组提交机制
WRITESET: 基于写集合机制
WRITESET_SESSION: 基于写集合,比writeset多了一个约束,同一个session中的事务last_committed按先后顺序递增
用于控制事务的检测算法,参数值为:OFF、 XXHASH64、MURMUR32
开启MTS(并行复制)功能后,务必将参数master_info_repostitory设置为TABLE,这样性能可以有50%~80%的提升。这是因为并行复制开启后对于元master.info这个文件的更新将会大幅提升,资源的竞争也会变大。
若将slave_parallel_workers设置为0,则MySQL 5.7退化为原单线程复制,但将slave_parallel_workers设置为1,则SQL线程功能转化为coordinator线程,但是只有1个worker线程进行回放,也是单线程复制。然而,这两种性能却又有一些的区别,因为多了一次coordinator线程的转发,因此slave_parallel_workers=1的性能反而比0还要差。
MySQL 5.7后的MTS可以实现更小粒度的并行复制,但需要将slave_parallel_type设置为LOGICAL_CLOCK,但仅仅设置为LOGICAL_CLOCK也会存在问题,因为此时在slave上应用事务的顺序是无序的,和relay log中记录的事务顺序不一样,这样数据一致性是无法保证的,为了保证事务是按照relay log中记录的顺序来回放,就需要开启参数slave_preserve_commit_order。
在使用了MTS(并行复制)后,复制的监控依旧可以通过SHOW SLAVE STATUS\G,但是MySQL 5.7在performance_schema库中提供了很多元数据表,可以更详细的监控并行复制过程。
读写分离首先需要将数据库分为主从库,一个主库用于写数据,多个从库完成读数据的操作,主从库之间通过主从复制机制进行数据的同步。
在应用中可以在从库追加多个索引来优化查询,主库这些索引可以不加,用于提升写效率。
读写分离架构也能够消除读写锁冲突从而提升数据库的读写性能。使用读写分离架构需要注意:主从同步延迟和读写分配机制问题。
主从同步具有延迟性,数据一致性会受到影响,可通过以下方式解决:
在写入数据库后,某个时间段内读操作就去主库,之后读操作访问从库。
先去从库读取数据,找不到时就去主库进行数据读取。该操作容易将读压力返还给主库,为了避免恶意攻击,建议对数据库访问API操作进行封装,有利于安全和低耦合。
根据业务特点和重要程度进行调整,比如重要的,实时性要求高的业务数据读写可以放在主库。对于次要的业务,实时性要求不高可以进行读写分离,查询时去从库查询。
该机制用于控制何时去主库写,何时去从库读,有以下两种方案实现:
代码中进行多数据源配置,根据操作类型进行路由分配,增删改时操作主库,查询时操作从库。
缺点是需要开发人员来实现,运维人员无从下手,如果其中一个数据库宕机了,就需要修改配置重启项目。
在应用和数据库之间做一个代理服务器,应用不直接访问数据库,而是访问代理服务器,由代理服务器根据路由规则决定走master还是slave。常见的数据库中间件有MySQL Proxy,MyCat。
grant replication slave on *.* to 'root'@'%' identified by 'root';
grant all privileges on *.* to 'root'@'%' identified by 'root';
show master status;
在配置文件中指定唯一id:server-id
change master to master_host='主库ip', master_port=主库端口号, master_user='主库用户名', master_password='主库密码', master_log_file='主库日志文件名',master_log_pos=主库position;
示例:
change master to master_host='192.168.159.132', master_port=3306, master_user='slave', master_password='123456', master_log_file='mysql-bin.000030',master_log_pos=730;
show slave status;
## Linux安装插件取名时使用.so
install plugin rpl_semi_sync_master soname 'semisync_master.so';
## Windows安装插件取名时使用.dll
install plugin rpl_semi_sync_master soname 'semisync_master.dll';
show variables like '%semi%';
set global rpl_semi_sync_master_enabled=1;
set global rpl_semi_sync_master_timeout=1000;
install plugin rpl_semi_sync_slave soname 'semisync_slave.dll';
set global rpl_semi_sync_slave_enabled=1;
show variables like '%binlog_group%';
set global binlog_group_commit_sync_delay=1000;
set global binlog_group_commit_sync_no_delay_count=100;
show variables like '%slave%';
stop slave;
set global slave_parallel_type='LOGICAL_CLOCK';
##线程数
set global slave_parallel_workers=8;
##从库中继日志
show variables like '%relay_log%';
set global relay_log_recovery=1;
set global relay_log_info_repository='TABLE';
start slave;
以上内容为个人学习理解,如有问题,欢迎在评论区指出。
部分内容截取自网络,如有侵权,联系作者删除。