目录

一、MySQL主从复制

1.1 MySQL复制的类型

1.2 工作原理

1.3 mysql的四种同步的方式

二、MySQL的读写分离

2.1 什么是读写分离

2.2 读写分离的好处

2.3 常见的MySQL读写分离

2.3.1 基于程序代码的内部实现

2.3.2 基于中间代理层实现

2.3.3 Amoeba

三、MySQL的主从复制和读写分离的部署实验

3.1 配置主从复制

3.1.1 主服务器配置(192.168.58.88)

3.1.2 从服务器配置(192.168.58.100)

3.1.3 验证主从同步

3.2 搭建amoeba实现读写分离(192.168.58.98)

3.2.1 安装java环境

3.2.2 配置amoeba

3.2.3 在客户端上测试(192.168.58.98)

四、数据库主从延迟是什么原因?解决方案?

4.1主从延迟是怎样定义的呢?与主从数据同步相关的时间点有三个

4.2哪些情况会导致主从延迟呢?

4.3 同步失败怎么去解决

五、总结问题


在生产环境中,如果对数据库的读和写都在一个数据库服务器中操作,会导致安全性和高可用都比较低。所以,我们都要通过主从复制来同步数据。

一、MySQL主从复制

1.1 MySQL复制的类型

①基于SQL语句的复制

②基于行的复制(ROW)

③混合类型的复制(MIXED)

1.2 工作原理

1.客户端将数据写入master节点的数据库中,master节点会提交事务,把数据保存在二进制日志中。

2.slave节点的I/O线程,去监听master的二进制日志的更新,当二进制日志发生更新的时候则会去向master的dump线程发出同不请求

3.master的dump线程当接收到slave的I/O请求后,会读取二进制文件的更新内容,然后发送给slave的I/O线程。

4.slave的I/O线程接收到数据后,会保存在slave的中继日志里

5.slave的sql进程会读取中继日志的内容,并且更新保存在数据库中

1.3 mysql的四种同步的方式

1、异步复制(Async Replication)
主库将更新写入Binlog日志文件后,不需要等待数据更新是否已经复制到从库中,就可以继续处理更多的请求。Master将事件写入binlog,但并不知道Slave是否或何时已经接收且已处理。在异步复制的机制的情况下,如果Master宕机,事务在Master上已提交,但很可能这些事务没有传到任何的Slave上。假设有Master->Salve故障转移的机制,此时Slave也可能会丢失事务。MySQL复制默认是异步复制,异步复制提供了最佳性能。

2、同步复制(Sync Replication)
主库将更新写入Binlog日志文件后,需要等待数据更新已经复制到从库中,并且已经在从库执行成功,然后才能返回继续处理其它的请求。同步复制提供了最佳安全性,保证数据安全,数据不会丢失,但对性能有一定的影响。

3、半同步复制(Semi-Sync Replication)
主库提交更新写入二进制日志文件后,等待数据更新写入了从服务器中继日志中,然后才能再继续处理其它请求。该功能确保至少有1个从库接收完主库传递过来的binlog内容已经写入到自己的relay log里面了,才会通知主库上面的等待线程,该操作完毕。
半同步复制,是最佳安全性与最佳性能之间的一个折中。
MySQL 5.5版本之后引入了半同步复制功能,主从服务器必须安装半同步复制插件,才能开启该复制功能。如果等待超时,超过rpl_semi_sync_master_timeout参数设置时间(默认值为10000,表示10秒),则关闭半同步复制,并自动转换为异步复制模式。当master dump线程发送完一个事务的所有事件之后,如果在rpl_semi_sync_master_timeout内,收到了从库的响应,则主从又重新恢复为增强半同步复制。
ACK (Acknowledge character)即是确认字符。

4、增强半同步复制(lossless Semi-Sync Replication、无损复制)
增强半同步是在MySQL 5.7引入,其实半同步可以看成是一个过渡功能,因为默认的配置就是增强半同步,所以,大家一般说的半同步复制其实就是增强的半同步复制,也就是无损复制。
增强半同步和半同步不同的是,等待ACK时间不同
rpl_semi_sync_master_wait_point = AFTER_SYNC(默认)
半同步的问题是因为等待ACK的点是Commit之后,此时Master已经完成数据变更,用户已经可以看到最新数据,当Binlog还未同步到Slave时,发生主从切换,那么此时从库是没有这个最新数据的,用户看到的是老数据。
增强半同步将等待ACK的点放在提交Commit之前,此时数据还未被提交,外界看不到数据变更,此时如果发送主从切换,新库依然还是老数据,不存在数据不一致的问题。

二、MySQL的读写分离

2.1 什么是读写分离

读写分离是让主数据库去处理事务(增、删、改),但是从数据库值去处理select查询的操作。

2.2 读写分离的好处

把查询和增删改分开,能提高效率。

因为数据库的写耗时比较高,但是读取的是比较快的,所以如果读和写在一起会严重影响了效率。

2.3 常见的MySQL读写分离

2.3.1 基于程序代码的内部实现

在代码中根据 select、insert 进行路由分类,这类方法也是目前生产环境应用最广泛的。
优点是性能较好,因为在程序代码中实现,不需要增加额外的设备为硬件开支;缺点是需要开发人员来实现,运维人员无从下手。
但是并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的Java应用,如果在程序代码中实现读写分离对代码改动就较大。

2.3.2 基于中间代理层实现

代理一般位于客户端和服务器之间,代理服务器接到客户端请求后通过判断后转发到后端数据库,有以下代表性程序:
MySQL-Proxy。MySQL-Proxy 为 MySQL 开源项目,通过其自带的 lua 脚本进行SQL 判断。
Atlas。是由奇虎360的Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。支持事物以及存储过程。

2.3.3 Amoeba

读取的请求发送给从服务器是,采用轮询调度算法
amoeba使用的java语言编写,配置文件为xml
amoeba主要负责对外的一个代理IP
访问这个IP时,发送的请求为“写”请求,则会转给主服务器
当发送的请求为读时,会通过调度转发给从服务器,使用轮询算法,轮流分配给两台从服务器
amoeba可以视为调度器,如果主服务器挂掉(单点故障),则会有MHA解决这个问题
由于使用MySQL Proxy需要写大量的Lua脚本,这些Lua脚本不是现成的,而需要自己编写,这对于并不熟悉MySQL Proxy内置变量和MySQL Protocol的人来说是非常困难的。Amoeba是一个非常容易使用,可移植性非常强的软件,因此它在生产环境中被广泛用于数据库的代理层。

三、MySQL的主从复制和读写分离的部署实验

主从复制+读写分离总概括图

配置环境

master    192.168.58.88

slave1     192.168.58.100

slave2     192.168.58.66

amoeba   192.168.58.98

3.1 配置主从复制

3.1.1 主服务器配置(192.168.58.88)

yum -y install ntp
 
vim /etc/ntp.conf

在尾行插入

server 127.127.58.0              #设置本地是时钟源,注意修改网段
fudge 127.127.58.0 stratum 8         #设置时间层级为8(限制在15内)
 
systemctl start ntpd

vim /etc/my.cnf
server-id = 1
log-bin=master-bin              #添加,主服务器开启二进制日志
log-slave-updates=true            #添加,允许从服务器更新二进制日志
binlog_format = MIXED
 
systemctl restart mysqld
 
mysql -u root -p
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.58.%' IDENTIFIED BY '123456';     
#给从服务器授权
FLUSH PRIVILEGES;
 
show master status;
 
#File 列显示日志名,Fosition 列显示偏移量

 

3.1.2 从服务器配置(192.168.58.100)

yum -y install ntp ntpdate
 
service ntpd start
/usr/sbin/ntpdate 192.168.58.88     #进行时间同步,指向Master服务器IP
 
crontab -e
*/30 * * * * /usr/sbin/ntpdate 192.168.58.88

1.#开启二进制日志
vim /etc/my.cnf
server-id = 11    #修改,注意id与Master的不同,两个Slave的id也要不同
relay-log=relay-log-bin    #添加,开启中继日志,从主服务器上同步日志文件记录到本地
relay-log-index=slave-relya-bin.index    #添加,定义中继日志文件的位置和名称,一般和relay-log在同一目录
relay_log_recovery = 1      #选配项
#当 slave 从库宕机后,假如 relay-log 损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的 relay-log,并且重新从 master 上获取日志,这样就保证了relay-log 的完整性。默认情况下该功能是关闭的,将 relay_log_recovery 的值设置为 1 时, 可在 slave 从库上开启该功能,建议开启。
 
 
2.#重启服务
systemctl restart mysqld.service 
 
3. #登入mysql,配置同步注意master_log_file和master_log_pos的值要和master查询的一致
mysql -uroot -p123456
change master to master_host='192.168.58.88',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=603;
 
4.#启动同步,如果报错,执行restart slave试试
start slave;
show slave status\G;
##以下两个必须要是YES
#Slave_IO_Running: Yes
#Slave_SQL_Running: Yes
 
#一般 Slave_IO_Running: No 的可能性:
1、网络不通
2、my.cnf配置有问题
3、密码、file文件名、pos偏移量不对
4、防火墙没有关闭

vim /etc/my.cnf

登录mysq数据库配置文件

3.1.3 验证主从同步

3.2 搭建amoeba实现读写分离(192.168.58.98)

3.2.1 安装java环境

################安装 Java 环境###############
1.#下载安装包:jdk-6u14-linux-x64.bin、amoeba-mysql-binary-2.2.0.tar.gz 
cd /opt
 
2.#把jdk复制到/usr/local下
cp jdk-6u14-linux-x64.bin /usr/local/
 
3.#赋予jdk权限并执行
chmod +x /usr/local/jdk-6u14-linux-x64.bin
cd /usr/local/
./jdk-6u14-linux-x64.bin  #一路回车到底,最后输入yes 自动安装
 
4.#jdk改个名字
mv jdk1.6.0_14/ jdk1.6
 
5.#配置环境并刷新
vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$AMOEBA_HOME/bin
6. #刷新配置文件,并查看
source /etc/profile  
 java -version

改名字

配置环境 vim /etc/profile

刷新文件产看java

3.2.2 配置amoeba

############## 安装amoeba ###########
 
1.#在/usr/local目录下创建amoeba目录
mkdir /usr/local/amoeba
 
2.#切换至opt解压amoeba
cd /opt/
tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba
 
cd /usr/local/ 切换至目录查看
 
 
3.#给目录/usr/local/amoeba赋予执行权限
chmod -R 755 /usr/local/amoeba/
 
4.#运行amoeba
/usr/local/amoeba/bin/amoeba  $
 
 
###########配置 Amoeba读写分离 ####
5.#先在Master、Slave1mysql上开放权限给 Amoeba 访问
grant all on *.* to test@'192.168.58.%' identified by '123456';
flush privileges;
 
6.#备份amoeba配置
cd /usr/local/amoeba/conf/
cp amoeba.xml amoeba.xml.bak
cp dbserver.dtd dbserver.dtd.bak
 
7.#修改amoeba配置
vim amoeba.xml
30 <property name="user">amoeba</property>
#设置登录用户名
32<property name="password">123456</property>
#设置密码
 
115<property name="defaultPool">master</property>
#设置默认池为master
118<property name="writePool">master</property>
#设置写池
119<property name="readPool">slaves</property>
#设置读池
 
vim dbServers.xml 
23 <!-- <property name="schema">test</property> -->
#23行注释
26<property name="user">test</property>
#设置登录用户
28 <!--  mysql password -->
#删除
29<property name="password">123456</property>
#解决28注释,添加密码
 
45<dbServer name="master"  parent="abstractServer">
#服务池名
48<property name="ipAddress">192.168.58.88</property>
#添加地址
 
52<dbServer name="slave1"  parent="abstractServer">
55<property name="ipAddress">192.168.58.100</property>
复制6行 添加另一从节点
59<dbServer name="slave2"  parent="abstractServer">
62<property name="ipAddress">192.168.58.66</property>
 
66<dbServer name="slaves" virtual="true">
#定义池名
72<property name="poolNames">slave1,slave2</property>
#写上从节点名
 
8.#启动amoeba,并测试
/usr/local/amoeba/bin/amoeba  start &
netstat -ntap |grep java  查看8066端口是否开启

1.创建amoeba目录

2.切换至opt下解压amoeba

3.给/usr/local/amoeba赋权(-R对目录下的子目录全部赋权)

4. 运行amoeba

5.在master和slave1和slave2上开放权限给amoeba访问

6.备份amoeba配置再去修改文件

cd /usr/local/amoeba/conf

vim  amoeba.xml

 vim dbServers.xml

 

7.启动amoeba

3.2.3 在客户端上测试(192.168.58.98)

1.#安装mariadb
yum install mariadb mariadb-server.x86_64 -y
2.在客户端服务器上测试
mysql -uamoeba -p123456 -h 192.168.58.98 -P8066
###通过amoeba 服务器代理访问mysql ,在通过客户端连接mysql 后写入的数据只有主服务
会记录然后同步给从服务器
在主服务器上:
use db_test;
create table test (id int(10),name varchar(10),address varchar(40));
3.#测试同步
在两台从服务器上:
stop slave;                                            #关闭同步
use db_test;
//在slave1上:
insert into test values('1','zhangsan','this_is_slave1');
//在slave2上:
insert into test values('2','lisi','this_is_slave2');
//在主服务器上:
insert into test values('3','wangwu','this_is_master');
//在客户端服务器上:
use db_test;
select * from test;        //客户端会分别向slave1和slave2读取数据,显示的只有在两个从服务器上添加的数据,没有在主服务器上添加的数据
insert into test values('4','qianqi','this_is_client');        //只有主服务器上有此数据
//在两个从服务器上执行 start slave; 即可实现同步在主服务器上添加的数据
start slave;
4.#测试读写分离
#停止slave1和slave2的slave同步功能
stop slave;
#在master、slave1和slave2上插入数据

1.安装mariadb

2. 登录并查看数据库,查看数据库

mysql -u amoeba -p123456 -h 192.168.58.98 -P8066

3.测试

在客户机上插入数据

在主服务器和从服务器上查看

4.测试读写分离

在客户机上插入数据

 

四、数据库主从延迟是什么原因?解决方案?

4.1主从延迟是怎样定义的呢?与主从数据同步相关的时间点有三个

主库执行完一个事务,写入binlog,我们把这个时刻记为 T1;
主库同步数据给从库,从库接受完这个binlog的时刻,记录为 T2;
从库执行完这个事务,这个时刻记录为 T3。
所谓主从延迟,其实就是指同一个事务,在从库执行完的时间和在主库执行完的时间差值,即 T3-T1。

4.2哪些情况会导致主从延迟呢?

①如果从库所在的机器比主库的机器性能差,会导致主从延迟,这种情况比较好解决,只需选择主从库一样规格的机器就好。
②如果从库的压力大,也会导致主从延迟。比如主库直接影响业务,大家可能使用会比较克制,因此一般查询都打到从库了,结果导致从库查询消耗大量CPU,影响同步速度,最后导致主从延迟。这种情况的话,可以搞一主多从架构,即多接几个从库分摊读的压力。另外,还可以把binlog接入到Hadoop这类系统,让它们提供查询的能力。
③大事务也会导致主从延迟。如果一个事务执行就要10分钟,那么主库执行完后,给到从库执行,最后这个事务可能就会导致从库延迟10分钟啦。日常开发中,我们为什么特别强调,不要一次性delete太多SQL,需要分批进行,其实也是为了避免大事务。另外,大表的DDL语句,也会导致大事务,大家日常开发关注一下哈。
④网络延迟也会导致主从延迟,这种情况你只能优化你的网络啦,比如带宽20M升级到100M类似意思等。
⑤如果从数据库过多也会导致主从延迟,因此要避免复制的从节点数量过多。从库数据一般以3-5个为宜。
⑥低版本的MySQL只支持单线程复制,如果主库并发高,来不及传送到从库,就会导致延迟。可以换用更高版本的Mysql,可以支持多线程复制。

4.3 同步失败怎么去解决

#忽略当前的错误执行下一步的同步

先 stop slave;

① slave数据库中:SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;

START SLAVE;

问题:I/O线程 一直处于connecting

第一件事,看laster error,报错项内容是为支点找不到

先 stop slave;

② slave数据库中:

CHANGE MASTER TO MASTER_LOG_FILE=‘mysql-bin.000001’,MASTER_LOG_POS=0;

首先遇到这个是因为binlog位置索引处的问题,生产环境下不要直接reset slave(删除change master 操作的);

reset slave会将主从同步的文件以及位置恢复到初始状态,一开始没有数据还好,有数据的话,相当于重新开始同步,可能会出现一些问题;

一般做主从同步,都是要求以后的数据实现主从同步,而对于旧的数据完全可以使用数据库同步工具先将数据库同步,完了再进行主从同步;

好了遇到上面的问题,正确做法是:

1.打开主(master)服务器,进入mysql

2.执行flush logs;//这时主服务器会重新创建一个binlog文件;

3.在主服务上执行show master status\G;显示如下:

4.来到从服务器的mysql;

5.stop slave;

6.change master to master_log_file='mysql-bin.000012',master_log_pos=154;//这里的file和pos都是上面主服务器master显示的。

7.start slave; //这时候就应可以了

五、总结问题

1、主从同步原理
首先client端(tomcat)将数据写入到master节点的数据库中,master节点会通知存储引擎提交事务,同时会将数据以(基于行、基于sql、基于混合)的方式保存在二进制日志中
SLAVE节点会开启I/O线程,用于监听master的二进制日志的更新,一旦发生更新内容,则向master的dump线程发出同步请求
master的dump线程在接收到SLAVE的I/O请求后,会读取二进制文件中更新的数据,并发送给SLAVE的I/O线程
SLAVE的I/O线程接收到数据后,会保存在SLAVE节点的中继日志中
同时,SLAVE节点钟的SQL线程,会读取中继日志钟的熟,更新在本地的mysql数据库中
最终,完成slave——>复制master数据,达到主从同步的效果
2、如何查看主从同步状态是否成功
在从服务器内输入命令 show slave status\G,查看主从信息进行查看,里面有IO线程的状态信息,还有master服务器的IP地址、端口、事务开始号,

当 slave_io_running 和 slave_sql_running 都显示为yes时,表示主从同步状态成功

3、如果I/O和SQL不是yes呢,你是如何排查的
首先排除网络问题,使用ping命令查看从服务是否能与主服务器通信

再者查看防火墙和核心防护是否关闭

接着查看从服务器内的slave是否开启

两个从服务器的 server-id 是否相同导致只能连上一台

master_log_file 和 master_log_pos 的值要是否与Master查询的一致

4、show slave status能看到哪些信息(比较重要的)
IO线程的状态信息

master服务器的IP地址、端口、事务开始位置

最近一次的报错信息和报错位置等

5、主从复制慢(延迟)有哪些可能
主服务器的负载过大,被多个睡眠或者僵尸线程占用,导致系统负载过大

从库硬件比主库差,导致复制延迟

主从复制单线程,如果主库写并发太大,来不及传送到从库,就会导致延迟。

慢SQL语句过多

网络延迟

MySQL的主从复制、读写分离(amoeba)相关推荐

  1. RDS 与 ECS 自建mysql 建议主从复制读写分离操作

    RDS 与 ECS 自建mysql 建议主从复制读写分离操作 一.RDS 作为主数据库,本实例使用的是mysql 8.0 登录 RDS 控制台,选择目标实例. 配置从实例读取数据使用的只读账号和授权数 ...

  2. MySQL搭建主从复制 读写分离 分库分表 MyCat高可用

    主从演示 读写演示 分表演示 主从复制 环境的介绍 系统环境:centos7.0 客户端连接工具:xshell 远程文件传输工具:xftp 服务器: 192.168.126.138(主) 192.16 ...

  3. Mysql数据库安装,基本命令,主从复制,读写分离,数据库的冷热备和数据库的还原,慢查询日志打开

    文章目录 1. 安装Mysql数据库 使用二进制安装Mysql数据库 使用yum安装Mysql 2.mysql的常用命令 3.慢查询开启 4.mysql数据库的冷备 5.数据库热备使用Xtraback ...

  4. java读取mysql配置文件_一文读懂 MySQL 主从复制读写分离

    文章已收录Github精选,欢迎Star:https://github.com/yehongzhi/learningSummary 前言 在很多项目,特别是互联网项目,在使用MySQL时都会采用主从复 ...

  5. mysql proxy 主从_【MYSQL知识必知必会】MySQL主从复制读写分离(基于mysql-proxy实现)...

    MySQL主从复制读写分离(基于mysql-proxy实现) http://mirror.bit.edu.cn/mysql/Downloads/MySQL-Proxy/mysql-proxy-0.8. ...

  6. MySQL之——MSS主从复制(读写分离)实现

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/52746393 前面,在博文<MySQL之--MS主从复制(读写分离)实现&g ...

  7. mysql主从复制于读写分离_MySQL主从复制读写分离

    mysql主从复制读写分离 master和slave时间同步 [[email protected]~]#ntpdate 172.18.0.1 [[email protected]~]#vim /etc ...

  8. 互联网架构阶段 数据库读写分离 Amoeba

    数据库的读写分离 一 .电商项目中数据库瓶颈 使用redis缓存减小数据库的压力 , 从而提升数据库的效率 单个数据库同时负责读写操作 , 底层可能会出现锁的现象: 同步锁 , 事务锁 , 乐观锁 , ...

  9. mysql5.7 读写分离_mysql5.7的主从复制+读写分离

    Mysql主从复制与读写分离 目录: 1.mysql主从复制工作原理 2.mysql读写分离原理,使用Amoeba中间代理层实现读写分离 3.在vmware中实现mysql主从复制+读写分离 一.My ...

  10. CentoOS7.9搭建mysql5.7分布式集群+主从复制+读写分离知识整理

    一.集群介绍 MySQL的高可用架构无论是社区还是官方,一直在技术上进行探索,这么多年提出了多种解决方案,比如MMM, MHA, NDB Cluster, Galera Cluster, InnoDB ...

最新文章

  1. NBT:牛瘤胃微生物组的参考基因组集
  2. Specification使用in
  3. 用户请求队列化_分布式消息队列选型分析
  4. android studio annotations,AndroidAnnotations在Android Studio中的配置
  5. 高维数据使用npy格式保存
  6. C语言'\0'(偶遇坑)
  7. 2021年高考成绩查询贵州分数线,2021年贵州省高考分数线
  8. su切换到oracle后怎么退出,linux下启动oralce和关闭oracle以及数据库实例化
  9. python自定义模块与模块调用
  10. C语言练习①一英寸是多少厘米?
  11. Unity:简单的蓄力技能的逻辑实现
  12. 存储系统(一)—— 存储器介绍
  13. c#中计算三角形面积公式,C#源代码—三角形面积、圆的面积
  14. 【推荐】两大APP与云账户红包SDK集成详情及Demon分享
  15. AT指令表(中文详解)
  16. 荣耀成为华为手机海外出货量增长发动机,小米已不是对手
  17. PS制作红色拟物化时钟icon图标
  18. 世界上最难的5种编程语言
  19. 定时器软件RH Timer for Mac了解一下
  20. 【算法】二维子矩阵的和

热门文章

  1. 《Excel 职场手册:260招菜鸟变达人》一第 18 招 怎样插入符号
  2. JB的测试之旅-项目流程规范
  3. 原生Js调用Fetch Api请求接口(新的Ajax解决方案)
  4. C++动态链接库(DLL)编程深入浅出(zz)
  5. 网络爬虫逆向(中大网校登录)
  6. cocos2dx uv动画溢出_宝爷Debug小记——Cocos2d-x(3.13之前的版本)底层BUG导致Spine渲染花屏...
  7. 微信小程序API的介绍
  8. SQL 代码创建数据库
  9. 普通人可以涉足股票投资量化吗?
  10. uniapp base64加密