mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

时间:2022-08-27 15:24:08

对于mysql复制一般来讲只有一个节点即能读又能写,其余节点只能读

复制的功用:

数据分布
负载均衡
备份
高可用和故障切换
mysql的升级测试

主从复制:
最基本条件:开启二进制日志
原理:
1、slave将自己扮演成客户端,向master请求二进制日志(若salve没有指明自己请求的位置,则master从第一个文件的最开始出发送给salve),slave得到二进制日志后将其保存在本地的中继日志中(IO线程)
2、master收到将二进制日志的事件读出来,响应给salve(dump线程)
3、slave得到二进制日志后将其保存在本地的中继日志中后slave还会开启一个线程,将中继日志的事件刷到磁盘中(SQL线程)

所以整个主从复制过程是由三个线程完成的:

从节点:
I/O Thread:从master中请求二进制日志,将其保存在中级日志中
SQL Thread:从中继日志中读取二进制文件,在本地完成重放
主节点:
dump Thread:为每个salve的I/O Thread启动一个dump线程,用于向其发送binary log event

主从复制的特点:

1、默认为异步复制
2、数据不一致比较常见

复制架构:M/S 、 M/M 、 环状复制

一主多从
从服务器还可以再有从服务器(mysql支持级联复制)
一从多主

mysql的异步复制:

mysql收到写操作后,只需保证本地写操作完成就立即返回给客户端写操作已完成,不会等待从服务器返回结果

对于非常繁忙的主节点,许多事务可能并行提交,那么用户请求过来后如何进行负载均衡呢?

这里不能使用lvs,因为要进行读写分离
使用一个工作在第七层模型的服务器,判断客户端过来的是写请求还是读请求。再进行调度。称为mysql七层反向代理(mysql的读写分离器)

如果说某个请求的相关数据集是一个刚刚接收了写操作的数据集上。他会将请求发给主节点而不是从节点(因此从节点会落后于主节点)

query cache原理(来自:https://blog.csdn.net/dongnan591172113/article/details/52084041

当mysql接收到一条select类型的query时,mysql会对这条query进行hash计算而得到一个hash值,然后通过该hash值到query cache中去匹配,如果没有匹配中,则将这个hash值存放在一个hash链表中,同时将query的结果集存放进cache中,存放hash值的链表的每一个hash节点存放了相应query结果集在cache中的地址,以及该query所涉及到的一些table的相关信息;如果通过hash值匹配到了一样的query,则直接将cache中相应的query结果集返回给客户端。如果mysql任何一个表中的任何一条数据发生了变化,便会通知query cache需要与该table相关的query的cache全部失效,并释放占用的内存地址。

有了query cache这种机制,前端调度应该怎么做呢?

某请求调度到某从节点,从节点收到后保存在query cache中。同一请求发送至同一从节点,直接从query cache中返回数据,这样虽然提高了缓存利用率,减少了IO开销。但这种机制不利于负载均衡,所以我们可以在前端进行memcache

主节点宕机了,将落后于主节点最少的从节点提升成主节点 (这种情况下基于gtid模式更加精确方便)

双主模式(互为主从 ):每一个节点即是主节点,又是对方的从节点。

这种模式下如何避免两个服务器之间来回复制?

每一个节点在本地保存二进制事件时会有一个server_id, 每个节点在本地重放二进制日志时,会保留server_id信息,另一个节点在读到后对比server_id是否与自己的相同。若相同,则判断为自己以前写过的数据,这样避免重复写入。

主主模型可能会带来数据不一致:

例如:主1:年龄大于30岁,工资翻倍,主2:工资大于3000的,年龄减一,有一个人正好30岁,怎么办?

多主模型:前一个服务器是后一个服务器的主(用的不多)

mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

一主多从:

在此模式下,主既要接受客户端段写请求,还要负载给从发送二进制日志。如何进行优化。

MySQL在5.x系列提供了Blackhole引擎–“黑洞”. 其作用正如其名字一样:任何写入到此引擎的数据均会被丢弃掉, 不做实际存储;Select语句的内容永远是空。 和Linux中的 /dev/null 文件完成的作用完全一致(参考:https://www.cnblogs.com/wt645631686/p/8086682.html
在主从之间添加一个分布式master,配置blackhole存储引擎,他起到一个中继的作用,他接收数据但在repilication时偷偷将数据丢掉,只是会把master的二进制日志供下层的slave来读取。
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

半同步复制

主节点在等待从节点返回,才返回。
在一主多从模式下,一般只给一个salve配置成半同步,其他配置成异步

复制过滤器

从节点指向复制的有限个数据库。在从节点上明确说明自己只在中继日志把需要的replication到本地。

接下来对: 主从、主主、半同步、复制过滤器进行演示:

主从复制的实现:

基于binlog:

主节点:
(1)启动二进制日志;
[mysqld]
log-bin=mysql-bin
(2)为当前节点设置一个全局唯一的ID号
[mysqld]
server_id=13)创建由复制权限的用户帐号

MariaDB [(none)]> grant replication slave, replication client on *.* to 'repluser'@'172.25.44.7' identified by 'repluser';

从节点:
(1)启动中继日志
[mysqld]
relay_log=relay-log
relay_log_index=relay-log.index2)为当前节点设置一个全局唯一的ID号
server_id=73)使用有复制权限的用户帐号连接至主服务器,并启动复制线程
change master to master_host='172.25.44.6', master_user='repluser',master_password='repluser',master_log_file='mysql-bin.000003',master_log_pos=423;
start slave;


完成上述配置,重启服务后,查看变量,看二进制日志是否打开:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
查看二进制文件:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
从:
重启服务后,查看中继日志是否打开,
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
查看server_id
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
在使用master的授权连接主服务器时,可以查看帮助:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

在完成授权后,查看slave的状态:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
发现IO线程和SQL线程都时NO,这时因为还没有开启复制线程
所以接下来开启复制线程:
查看帮助:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
不指定的话两个线程都打开
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
这时查看状态为YES
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
看到两个YES,基本上就成功了
测试:
主:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
从:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

主从架构中存在的问题:

1、一般来讲,从节点绝不应该接受写操作,以免数据不一致
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
这一项默认为off,将其设置为on
可以看到,即使我把这一项设置为on,还是可以进行写操作
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
原因是:此限制岁拥有super权限的用户无效
要想限制所有人:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
此线程不会组织SQL线程从本地读取中继日志进行写操作。因为它不是通过线程连接进来进行写操作的

2、如何保证主从复制的事务安全
(1)master:
主服务器在数据提交时,为了保证数据的持久性、可靠性等特点,都应该立即将事务从内存写入磁盘中,即使不写入数据文件中至少也应该写入事务日志中。
二进制日志为了加速写操作,在内存中有缓冲。因此一些和事务相关得提交语句,及提交之前的一些写语句仍然可能在二进制日志的内存缓冲区,并不在二进制日志中。这就意味着从服务器复制不到。、
明明事务已经提交,但从服务器上并没有提交。
为了避免以上问题:即主服务器事务提交后,从服务器能尽快获得一份和此事务相关的语句,并在本地运行一遍,至少也得保存在中继日志中。这样,当主节点因为事故宕机后,从节点的事务也是完整的

在master节点启用sync_binlog=ON  在事务提交时,必须立即将binlog缓冲区中记录下来的时间刷新代二进制日志中。
若用到InnoDB存储引擎:
innodb_use_global_flush_log_at_trx_commit=ON
innodb_support_xa=ON       

(2)slave 上:
skip_salve_start=ON (在slave的mysql开启后,不自动启动复制线程)

在从节点上有两个info文件。他们有什么作用呢?
在MySQL 5.6.2之前,slave记录的master信息以及slave应用binlog的信息存放在文件中,即master.info与relay-log.info。

mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

master.info文件:( IO Thread)
该文件的作用:记录已经复制到哪个主节点的哪一个二进制的哪一个位置。用的是什么身份、密码复制的。
这也就是为什么默认情况下,启动mysql服务后会自动连接到主节点。
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
relay-log.info文件:(SQL Thread)
用来记录本地已经复制到哪个二进制日志的哪一个位置,保存在中继日志的哪个位置。
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

(3)
master:
sync_master_info :每间隔多少事务刷新master.info,如果是table(innodb)设置无效,每个事务都会更新
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
slave: 默认为10000,即每10000次sync_relay_log事件会刷新到磁盘。为0则表示不刷新,交由OS的cache控制
sync_relay_log_info:每间隔多少事务刷新relay-log.info,如果是table(innodb)设置无效,每个事务都会更新
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
两个线程的执行进度(偏移量)都保存在文件中.IO thread的执行状态信息保存在master.info文件,SQL thread的执行状态信息保存在relay-log.info文件。系统运行正常的情况下,这种模式到目前为止还没有问题。需要注意的是这些文件被修改后不是同步写入磁盘的,每当系统发生crash,存储的偏移量可能都不准确.MySQL 5.5通过两个参数修复了该问题,使用sync_master_info=1和sync_replay_log_info=1 来保证Slave 的两个线程每次写一个事务就分别向两个文件同步一次 IO thread和SQL thread当前执行的信息。当然同步操作不是免费的,频繁更新磁盘文件需要消耗性能(参考:http://blog.itpub.net/22664653/viewspace-1752588/)

问题::在mysql主从复制过程中,如果主节点已经运行了一段时间并且有大量数据,这时候如何配置并启动slave?
在主服务器上进行备份,备份的时候记录二进制日志的文件名和posiition,在从服务器将数据导入(就像恢复数据一样)。并在从服务器上指明从备份那一刻的二进制日志和position处开始复制。

主主复制:

(1)主主复制会导致数据不一致,因此慎用!
两个节点互为主从,所以两个节点都启动二进制日志和中继日志。
(2)自动增长id:
配置node1使用奇数id:
auto_increment_increment = 1
auto_increment_offset =2
配置node2使用偶数节点:
auto_increment_increment = 2
auto_increment_offset =2

mysql中有自增长字段,在做数据库的主主同步时需要设置自增长的两个相关配置:auto_increment_offset和auto_increment_increment。

auto_increment_offset表示自增长字段从那个数开始,他的取值范围是1 .. 65535
auto_increment_increment表示自增长字段每次递增的量,其默认值是1,取值范围是1 .. 65535

在主主同步配置时,需要将两台服务器的auto_increment_increment增长量都配置为2,而要把auto_increment_offset分别配置为1和2.
这样才可以避免两台服务器同时做更新时自增长字段的值之间发生冲突。(参考:https://www.cnblogs.com/DBArtist/p/auto_increment.html)

配置步骤:
(1)各节点使用一个唯一的sever_id;
(2)都启动binary log 和 relay log;
(3)创建拥有复制权限的用户帐号;
(4)定义自动增长id的字段的数值范围奇偶;
(5)均把对方主为主节点。并启动复制线程;

由于我之前已经做过主从复制,在配置主主复制之前,我先将服务器恢复至最初状态。我用的方法比较简单粗暴——直接删除/var/lob/mysql下的数据(建议生产环境中不要这么干!)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

node1:server6
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

node2:server7(配置于node1类似,这里就不演示了)

测试:
在node1上写数据:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

node2查看:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
在node2上写数据:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
node1查看:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

以上就实现了主从复制,
但是主主复制配置文件中auto_increment_increment和auto_increment_offset只能保证主键不重复,却不能保证主键有序。

半同步复制

必须是MySQL5.5或者以上

master:
MySQL必须有自动加载功能,即have_dynamic_loading变量为YES(因为我们是在MySQL里面来加载安装这个功能插件)
查看是否具有自动加载功能:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
查看插件所在目录
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

semisync_master.so semisync_slave.so 这两个文件就是就是半同步插件所对应的配置文件
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
主安装rpl_semi_sync_master插件:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

可以看到插件已经被安装上了:
MariaDB [(none)]> show plugins;
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
查看与半同步有关的变量:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
rpl_semi_sync_master_enabled :是否启用自己为半同步复制的主节点
rpl_semi_sync_master_timeout:等待从节点的超时时间

可以看到插件的状态为off
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
开启插件:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

创建用户并授权
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

从:
安装插件
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

开启插件:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
查看状态发现状态依旧时off,没关系
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
使用master授权的用户连接到master,并开启复制线程
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

测试:
主写数据:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
从查看:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
这时再查看从的半同步插件的状态,发现已经开启了
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)
查看主节点的参数:
mysql总结3(复制:M/S(异步,半同步)、M/M,复制过滤器)

复制过滤器:

让从节仅复制指定的数据库,或者指定数据库地指定表;
有两种实现方式:
(1)主服务仅向二进制日志中记录与特定数据库(特定表)相关的事件
问题:时间还原无法实现:不建议使用;