首页 > 代码库 > MySQL主从复制(一)

MySQL主从复制(一)

web一般是拒绝用户上传的,webdav可以实现数据上传

MySQL的扩展方式:

scale up:

scale out:

一、MySQL的扩展:

复制:每个node都有相同的数据集

从node请求主node的二进制日志,在本地进行重放实现

复制的作用:

数据分布:

负载均衡://读均衡,写操作不能负载均衡

数据备份://主node挂了,切换从为主 //冷备是最可靠的

高可用性能提升

可以写脚本实现故障转移。//mysql内部没有提供故障转移

MySQL升级测试:

【master】【slave】 //主从复制功能,主node必须启用二进制日志功能。

slave使用msyql协议请求master的二进制日志文件事件

master所有的写操作,除了在本地保存到数据库中,还会将写入[语句]保存到二进制日志

slave请求binary log的时候,可以指定位置,不指定的话

    就从第一个文件的最开始,逐个发送给slave

    从node收到master二进制日志后,保存到自己的中继日志中,记录读取到的位置[position]

master启动一个dump线程接受slave的请求,然后用dump线程响应客户端

slave留到中继日志中,然后在本地reply一次

二、复制相关线程:

主node:

主node的dump线程;为每个slave的I/O线程启动一个dump线程,用于向其发送binary log events

从node:

io thread:从node负责从master获取并保存到中级日志

sql thread: 读取并应用中级日志

从node需要保存binary log吗?

binary log:用于实现重放和恢复

但是一个slave可以其另外一个slave的master

//slave有自己的slave的话,该slave需要开启二进制日志

级联复制:

[master]--[slave]--[slave]

三、mysql复制的特点:

1.异步,主node并不需要等待从node返回写入结果

同步问题:一旦网络故障,master不能访问,将瘫痪

异步问题:通过slave未必能读到完整的数据

slave会落后于master的内容

好处:在master上操作失误,可以在slave上进行还原,slave切换为主

例如在master上误操作:drop tables

2.延迟:

master在二进制日志中写入的速度一定会慢于本地执行的速度

而slave获取二进制的速度也会慢于二进制日志的写入速度

本地执行>二进制日志>slave获取二进制日志

调度器/LB   //七层调度,能够识别sql语句的写和读操作,并且能够实现负载均衡

/   |\

      []   []   []

//调度器一般称为:r/w spliter :读写分离

从node不可避免的要落后于master,也可以把最新的请求,调度到master进行读

r/w spliter:检查状态

mysql的query cache:假如查询调度到同一个slave提高缓存命中率,但是损害LB效果

可以在[调度器/LB] + memcahed //

slave宕机:重新调度即可

master宕机:不能执行w操作。可以把一个slave提升为master

如何选取哪一个为主:

A:1,2,3

B:1,2,5

C:1,2,3,4

//选举哪一个呢?各有自己的

//恢复有很多问题,

在mysql 5.6之后,引入了gtid:全局事务id

在此之前tid都是本地的,无法判断哪一个slave完成的事务多

A要想成为master:从B获取5,从C获取4,然后自己成为master

//这种方案,不推荐,很难实现。需要结合gtid和oracle为mysql提供的大量的工具实现

其他方案:

corosync高可用mysql

[master][passive]   [slave][slave]

\ /

[共享存储]

//passive节点和master共享vip,故障转移即可

SAN:存储区域网络

passive和master可使用共享存储

但是共享存储:存在单点故障

drbd:分布式磁盘快识别,两个块设备实现跨主机同步

MySQL的内存和io消耗量比较大

硬件性能也非常好

到一定阶段就再扩展,性能可能不会上升,反而会下降

四、如何实现节点间数据同步 //scale out

方案一:共享存储

【LB】

/    \

      []     []

\   /

[  ] //共享存储,需要使用集群fs

//对数据施加锁,对于集群fs来说,他的扩展数量是有限的,到达4-8个,差不多到上线了

//该方案可看不可用

方案二:多个数据集

【LB】

/\

      [][]

       ||

      [][] //使用副本集,一个node rw,其他node只能读

//每一个node保存完整的数据副本,只有一个node接收w请求,其他节点都通过同步或者复制的机制事先复制。

双主模型:

A和B都即是主node也是对方的从node

[A][B]

[2][relay][file][2][relay][file]

//2:二进制日志 

//A和B本地有数据文件、中继日志、二进制日志

通过serverid避免循环复制,根据serverid区分是自己传输给别人的。

A和B都能读和写

读请求被负载了,写请求虽然被LB了,但是实际还是需要A和B都写入

目的:冗余,不用做读写分离了,实现了HA

双主模型可能会导致数据不一致?

两个节点互为条件的,

tom 20岁

A:年龄>=20的工资翻倍

B:年龄大于20的,减去2岁,

那么最后怎么合并

MMM:双主模型解决方案

MHA:现在用的较多

percona:Galera-Cluster:在块级别实现复制 //较可靠的方案

mysql的主从复制:

1.异步复制

2.主从复制不一致比较常见

复制架构:

1.M/S 

2.M/M 

3.环状复制:每一个node都是上家的slave,又是下家的master

一主多从,一从再从:级联复制

一从只能有一个主

现在一从可以多主,可以从两个master复制不同的数据库

Mairadb 5.6 之后的版本,支持最后进行汇聚

主从

master需要接受w请求,并且启动n个线程,分发二进制日志给各slave

//master的压力依然有点大

如果master只需要复制一份二进制日志

级联可以实现 

master->slave1-->[A,B] //slave1负责读和二进制日志分发

master->black hole引擎->[A,B] //black hole引擎所在node不存储数据,只负责分发二进制日志

二进制日志事件记录格式:

STATEMENT 基于语句的

ROW 基于行的,最好的方案,但是最占用空间

MIXED 混合模式,这种方案

演示的模型:

主从、主主、半同步复制(google)、复制过滤

半同步复制:

一主多从

master接受到请求后,至少等待一个从node同步完成,并告诉master数据已经存储ok,才会返回给client ok

//一个slave同步,其他异步:半同步模型

复制过滤:

主从复制架构中,主有10个库,但是从只想复制5个库

过滤器:可以在主node过略,也可以在slave实现

主:二进制日志记录的时候,只记录指定的库,因此从只能获取有限的二进制日志

从:浪费带宽,我只要5个,但是你给我发送10个

五、实现主从复制

192.168.100.67 master 

192.168.100.68 slave 

配置过程:

master:

1.启动二进制日志

2.为当前node设置一个全局唯一的id号

3.创建一个有复制 权限的用户账号

replication slave,replication client //权限

slave:

1.启动中继日志

2.位当前node设置一个全局唯一的id号

3.使用有复制权限的用户账号连接至master,并启动复制线程

master 

vim my.cnf 

[mysqld]

log-bin=mysql-bin   //注意log_bin和log-bin都可以使用,建议统一

server-id=1

innodb_file_per_table=ON

skip_name_resolve=ON

systemctl start mariadb.service 

mysql> show global variables like ‘%log%‘

查看log_bin是否启用

mysql> show logs //查看二进制日志

mysql> show variables like ‘%server%‘

mysql> grant replication slave,replication client on *.* to ‘repluser‘@‘172.16.%.%‘ identified by ‘replpass‘;

注意卡其3306端口的防火墙

slave:

relay_log=reley_log 

relay_log_index=relay-log.index

server-id=7 //

innodb_file_per_table=ON

skip_name_resolve=ON 

systemctl start mariadb.service 

mysql> show gloabl variables like ‘%log%‘;

rely_log = rely_log //日志开启

mysql> show global variables like ‘%server%‘;

change master to master_host=‘192.168.100.67‘,master_user=‘repouser‘,master_password=‘repopass‘,maser_log_file=‘master-bin.00003‘,master_log_pos=245;  

master_user= //

master_host= //主机

master_port= //端口

master_password=

master_connect_retry= //多长时间重连一次,假如不能连接的话

master_log_pos= //复制的二进制日志的位置

master_heartbeat_period= //多长时间进行一次心跳检测

ignore_server_ids= //忽略哪些server id 的

show slave status //查看自己的状态

help start //启动复制线程

start slave; //默认启动sql_thread和io_thread

show slave staus ; //stop slave关闭线程

master:

crete database mydb;

show master status //查看二进制文件到哪一步了

slave:

show slave status;

//查看复制到哪里了


MySQL主从复制(一)