详解MySQL主从复制及读写分离


Posted in MySQL onMay 07, 2021

前言

在企业实际应用中,成熟的业务通常数据量都比较大,而单台MySQL服务器在安全性、高可用性和高并发方面都无法满足实际的需求,我们可以在多台MySQL服务器(Master-Slave)部署 主从复制来实现同步数据,再通过 读写分离来提升数据库的并发负载能力。有点类似于rsync,但是不同的是rsync是对磁盘文件做备份,而mysql主从复制是对数据库中的数据、语句做备份。

一、相关概述

主从复制:主数据库(Master)发送更新事件到从数据库(Slave),从数据库读取更新记录,并执行更新记录,使得从数据库的内容与主数据库保持一致。

(一)MySQL 支持的复制类型

  • 基于语句的复制(STATEMENT)。在主库上执行的 SQL 语句,在从库上执行同样的语句。MySQL 默认采用基于语句的复制,效率比较高。
  • 基于行的复制(ROW)。把改变的内容复制过去,而不是把命令在从库上执行一遍。
  • 混合类型的复制(MIXED)。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。

(二)MySQL主从复制的工作过程

详解MySQL主从复制及读写分离

1.Master 服务器保存记录到二进制日志

  • MySQL主库上进行的增、删、改的数据更新,都会按顺序写入到自己的二进制日志(Binary log)当中

2.Slave 服务器复制Master 服务器的日志

  • 然后MySQL从库开始一个I/O线程连接主库,读取主库的二进制日志,备份到从服务器的==中继日志(Relay log)==当中。如果已经跟上主库,它会睡眠并等待Master 产生新的事件,I/O线程将这些事件写入中继日志

3.Slave 服务器重放复制过来的日志

  • 然后从库打开SQL线程,SQL线程读取I/O线程写入的中继日志,并且根据中继日志的内容更新从库的数据,使其与主库中的数据一致

重点:复制过程有一个很重要的限制,即复制在 Slave 上是串行化的,也就是说Master 上的并行更新操作不能在 Slave 上并行操作

二、读写分离

(1)读写分离的概念

读写分离:读写分离就是只在主服务器上写,只在从服务器上读。基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。

(2)读写分离的作用

  •  因为数据库的"写"(写10000条数据可能要3分钟)操作是比较耗时的。但是数据库的"读"(读10000条数据可能只要5秒钟)。
  • 所以读写分离,解决的是,数据库的写入,影响了查询的效率。注意:数据库不一定要读写分离,如果程序使用数据库较多时,而更新少,查询多的情况下会考虑使用。利用数据库主从同步,再通过读写分离可以分担数据库压力,提高性能

(3)MySQL 读写分离原理

  • 读写分离就是只在主服务器上写,只在从服务器上读
  • 基本的原理是让主数据库处理事务性查询,而从数据库处理 select 查询
  • 数据库复制被用来把主数据库上事务性查询导致的变更同步到集群中的从数据库

(4)常见的 MySQL 读写分离

1)基于程序代码内部实现

1.在代码中根据 select、insert 进行路由分类,这类方法也是目前生产环境应用最广泛的。

2.优缺点:

  • 优点是性能较好,因为在程序代码中实现,不需要增加额外的设备为硬件开支;
  • 缺点是需要开发人员来实现,运维人员无从下手。

3.并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的Java应用,如果在程序代码中实现读写分离对代码改动就较大。

2)基于中间代理层实现

1.代理一般位于客户端和服务器之间,代理服务器接到客户端请求后通过判断后转发到后端数据库,有以下代表性程序:

  • MySQL-Proxy:MySQL-Proxy 为 MySQL 开源项目,通过其自带的 lua 脚本进行SQL 判断。
  • Atlas:是由奇虎360的Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。支持事物以及存储过程。
  • Amoeba:由陈思儒开发,作者曾就职于阿里巴巴。该程序由Java语言进行开发,阿里巴巴将其用于生产环境。但是它不支持事务和存储过程。

2.由于使用MySQL Proxy需要写大量的Lua脚本,这些Lua脚本不是现成的,而需要自己编写,这对于并不熟悉MySQL Proxy内置变量和MySQL Protocol的人来说是非常困难的。

3.Amoeba是一个非常容易使用,可移植性非常强的软件,因此它在生产环境中被广泛用于数据库的代理层。

三、MySQL主从复制实验部署

需要的相关软降包
amoeba-mysql-binary-2.2.0.tar.gz
jdk-6u14-linux-x64.bin
mysql压缩包

详解MySQL主从复制及读写分离

(1)主从复制实验步骤及准备

实验步骤
第一步:客户端client访问代理服务器amoeba
第二步:代理服务器读写判断
写操作:写入到主服务器
第三步:主服务器将增删改写入自己二进制日志
第四步:从服务器将主服务器的二进制日志同步至自己中继日志
第五步:从服务器重放中继日志到数据库中
读操作:直接访问从服务器
最终结果:降低负载,起到负载均衡作用
主机 操作系统 IP地址 所需工具/软件/安装包

Amoeba CentOS7  192.168.71.10 jdk-6u14-linux-x64.bin、amoeba-mysql-binary-2.2.0.tar.gz
Master CentOS7 192.168.71.12 ntp 、 mysql-boost-5.7.20.tar.gz
Slave1 CentOS7 192.168.71.13 ntp 、ntpdate 、 mysql-boost-5.7.20.tar.gz
Slave2 CentOS7 192.168.71.14 ntp 、ntpdate 、mysql-boost-5.7.20.tar.gz
客户端 CentOS7 192.168.71.15  

1.关闭防火墙及安全机制

四台服务器都要关闭

systemctl stop firewalld
systemctl disable firewalld
setenforce 0

2.安装时间同步服务ntp

(1)主服务器

yum -y install ntp

vim /etc/ntp.conf
##---------末尾添加---------
server 127.127.71.0           #设置本地是时钟源,注意修改网段
fudge 127.127.71.0 stratum 8  #设置时间层级为8(限制在15内)

service ntpd start

详解MySQL主从复制及读写分离

(2)两个从服务器

yum -y install ntp ntpdate

service ntpd start

/usr/sbin/ntpdate 192.168.71.12  #进行时间同步,指向Master服务器IP

crontab -e     #设置计划任务每个半个小时同步一次时间
*/30 * * * * /usr/sbin/ntpdate 192.168.71.12

详解MySQL主从复制及读写分离

详解MySQL主从复制及读写分离
详解MySQL主从复制及读写分离

3.主服务器的mysql配置

vim /etc/my.cnf
server-id = 1
log-bin=master-bin       #添加,主服务器开启二进制日志
log-slave-updates=true   #添加,允许从服务器更新二进制日志

systemctl restart mysqld

mysql -u root -p
grant replication slave on *.* to 'myslave'@'192.168.71.%' identified by '123'; #对从服务器提权
#grant 授权
#replication 复制
#允许网段为192.168.71的使用密码123对所有表库都可以复制

flush privileges;

show master status;
#File 列显示日志名,Fosition 列显示偏移量

详解MySQL主从复制及读写分离

4.从服务器的mysql配置

Slave1服务器:192.168.163.13
Slave2服务器:192.168.163.14

1)修改配置文件

vim /etc/my.cnf
#修改,注意id与Master的不同,两个Slave的id也要不同
server-id = 2

#添加,开启中继日志,从主服务器上同步日志文件记录到本地
relay-log=relay-log-bin

#添加,定义中继日志文件的位置和名称
relay-log-index=slave-relay-bin.index

systemctl restart mysqld

slave1

详解MySQL主从复制及读写分离

slave2

详解MySQL主从复制及读写分离

2)从服务器 对数据库进行操作

mysql -u root - p123
change master to master_host='192.168.71.12',master_user='myslave',master_password='123',master_log_file='master-bin.000002',master_log_pos=306; #show master status;所输出的二进制文件和位置点一样
     #配置同步,注意master_log_file 和master_log_pos的值要与Master查询的一致
	 
start slave;                     #启动同步,如有报错执行reset slave;
show slave status\G;             #查看Slave 状态
//确保 IO 和 SQL 线程都是Yes,代表同步正常。
Slave_IO_Running:Yes            #负责与主机的io通信
Slave_SQL_Running:Yes           #负责自己的slave mysql进程

详解MySQL主从复制及读写分离
详解MySQL主从复制及读写分离
详解MySQL主从复制及读写分离
详解MySQL主从复制及读写分离

5.验证结果

主服务器上创建一个库验,在从服务器上查看

详解MySQL主从复制及读写分离

详解MySQL主从复制及读写分离

四、MySQL读写分离实验

Amoeba服务器(192.168.153.30)
安装Java 环境
因为Amoeba 基于是jdk1.5 开发的,所以官方推荐使用jdk1.5或1.6版本,高版本不建议使用。

1)创建jdk java环境

cd /opt/
#将jdk-6u14-linux-x64.bin 和 amoeba-mysql-binary-2.2.0.tar.gz上传到/opt目录下

cp jdk-6u14-linux-x64.bin /usr/local/
cd /usr/local/
chmod +x jdk-6u14-linux-x64.bin
./jdk-6u14-linux-x64.bin
//按yes,按enter

mv jdk1.6.0_14/ /usr/1ocal/jdk1.6

vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=SCLASSPATH:$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

source /etc/profile
java -version

详解MySQL主从复制及读写分离
详解MySQL主从复制及读写分离
详解MySQL主从复制及读写分离

2)安装 Amoeba软件

mkdir /usr/local/amoeba
tar zxvf /opt/amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
chmod -R 755 /usr/local/amoeba/
/usr/local/amoeba/bin/amoeba
//如显示amoeba start|stop 说明安装成功

详解MySQL主从复制及读写分离

3)在主从服务器的mysql上授权

Master服务器:192.168.71.12
Slave1服务器:192.168.71.13
Slave2服务器:192.168.71.14

先在Master、Slave1、Slave2 的mysql上开放权限给 Amoeba 访问

grant all on *.* to 'test'@'192.168.163.%' identified by 'abc123';

详解MySQL主从复制及读写分离

4)配置amoeba服务在阿米巴上配置

cd /usr/local/amoeba/conf/

cp amoeba.xml amoeba.xml.bak     #对配置文件备份
vim amoeba.xml                   #修改amoeba配置文件

<property name="user">amoeba</property>          #30行修改

<property name="password">abc123</property>      #32行修改 客户端连接amoeba服务器的密码

<property.name="defaultPool">master</property>   #115行修改 设置默认池

<property name="writePool">master</property>     #117行去掉注释 设置master为写池
<property name="readPool">slaves</property>		 #slaves 为读池

详解MySQL主从复制及读写分离

cp dbServers.xml dbServers.xml.bak
vim dbServers.xml                     #修改数据库配置文件

<!-- <property name="schema"> test</property> -->      #23行,注释掉   作用: 默认进入test库以防mysql 中没有test库时,会报错

<property name="user">test</property>                  #26行,修改主从服务器上提权的用户和密码

<property.name-"password">123</property>           #28-30行,去掉注释

<dbServer name= "master" parent="abstractServer">      #45行,修改,设置主服务器的名Master

<property name= "ipAddress">192.168.71.12</property>  #48行,修改,设置主服务器的地址

<dbServer name="slave1"  parent="abstractServer">      #52行,修改,设置从服务器的名slave1

<property.name="ipAddress">192.168.71.13</property>   #55行,修改,设置从服务器1的地址

<dbServer name="slave2 " parent="abstractserver">      #59行,复制上面6行粘贴,设置从服务器2的名slave2和地址
<property, name="ipAddress">192.168.71.14</property>

<dbServer name="slaves" virtual="true">                #65行,修改

<property name="poolNames">slave1,slave2</property>    #71行,修改

/usr/local/amoeba/bin/amoeba start&      #启动Amoeba软件,按ctrl+c 返回
netstat -anpt | grep java               #查看8066端口是否开启,默认端口为TCP 8066

详解MySQL主从复制及读写分离
详解MySQL主从复制及读写分离

详解MySQL主从复制及读写分离

5)测试读写分离

在客户端服务器上测试

yum install -y mysql mysql-server #快速安装mysql,也可以选择编译安装

mysql -u amoeba -pabc123 -h 192.168.71.20 -P8066

详解MySQL主从复制及读写分离

主从服务 v器上都可以看到该表

详解MySQL主从复制及读写分离

通过amoeba服务器代理访问mysql ,在通过客户端连接mysql后写入的数据只有主服务会记录,然后同步给从服务器

stop slave;                                    #关闭同步写入数据
use school;
//在slave1上:
insert into test1 values('1','slave1');

//在slave2上:
insert into test1 values('2','slave2');

在主服务器上插入数据

insert into test1 values('3','master');

在客户端中向表插入数据

//在客户端服务器上:
use school;
select * from test1;    //客户端会分别向slave1和s1ave2读取数据,显示的只有在两个从服务器上添加的数据,没有在主服务器上添加的数据

insert into test1 values('4','climet');   //只有主服务器上有此数据

详解MySQL主从复制及读写分离

在主服务器上查看数据

详解MySQL主从复制及读写分离

同时开启两个从服务器,查看表格记录

详解MySQL主从复制及读写分离

到此这篇关于详解MySQL主从复制及读写分离的文章就介绍到这了,更多相关MySQL主从复制及读写分离内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
jdbc使用PreparedStatement批量插入数据的方法
Apr 27 MySQL
详解MySQL 联合查询优化机制
May 10 MySQL
MySQL 数据恢复的多种方法汇总
Jun 21 MySQL
Mysql数据库中datetime、bigint、timestamp来表示时间选择,谁来存储时间效率最高
Aug 23 MySQL
MySQL中连接查询和子查询的问题
Sep 04 MySQL
一文简单了解MySQL前缀索引
Apr 03 MySQL
MySQL 数据库范式化设计理论
Apr 22 MySQL
MySQL 条件查询的常用操作
Apr 28 MySQL
Mysql 文件配置解析介绍
May 06 MySQL
MySQL批量更新不同表中的数据
May 11 MySQL
MySQL中JOIN连接的基本用法实例
Jun 05 MySQL
MySQL实现用逗号进行拼接、以逗号进行分割
Dec 24 MySQL
MySQL 表空间碎片的概念及相关问题解决
MySQL kill不掉线程的原因
May 07 #MySQL
MySQL数字类型自增的坑
May 07 #MySQL
MySQL获取所有分类的前N条记录
May 07 #MySQL
教你解决往mysql数据库中存入汉字报错的方法
MySQL时间设置注意事项的深入总结
仅用一句SQL更新整张表的涨跌幅、涨跌率的解决方案
May 06 #MySQL
You might like
zf框架的校验器InArray使用示例
2014/03/13 PHP
php实现在服务器上创建目录的方法
2015/03/16 PHP
javascript使用中为什么10..toString()正常而10.toString()出错呢
2013/01/11 Javascript
jquery垂直公告滚动实现代码
2013/12/08 Javascript
改变隐藏的input中value的值代码
2013/12/30 Javascript
jqTransform美化表单
2015/10/10 Javascript
JavaScript学习小结之被嫌弃的eval函数和with语句实例详解
2016/08/01 Javascript
AngularJS路由切换实现方法分析
2017/03/17 Javascript
微信小程序tabbar不显示解决办法
2017/06/08 Javascript
分享19个JavaScript 有用的简写写法
2017/07/07 Javascript
Angular ng-animate和ng-cookies用法详解
2018/04/18 Javascript
微信小程序商品详情页的底部弹出框效果
2020/11/16 Javascript
vue检测对象和数组的变化分析
2018/06/30 Javascript
Node.js实现用户评论社区功能(体验前后端开发的乐趣)
2019/05/09 Javascript
解决element-ui里的下拉多选框 el-select 时,默认值不可删除问题
2020/08/14 Javascript
html+vue.js 实现漂亮分页功能可兼容IE
2020/11/07 Javascript
[04:31]2016国际邀请赛中国区预选赛妖精采访
2016/06/27 DOTA
Python调用微信公众平台接口操作示例
2017/07/08 Python
Python实现螺旋矩阵的填充算法示例
2017/12/28 Python
Python实现获取nginx服务器ip及流量统计信息功能示例
2018/05/18 Python
Python colormap库的安装和使用详情
2020/10/06 Python
基于Python爬取股票数据过程详解
2020/10/21 Python
python实现学生信息管理系统源码
2021/02/22 Python
荷兰网上买鞋:MooieSchoenen.nl
2017/09/12 全球购物
Harrods美国:英国最大的百货公司
2018/11/04 全球购物
空乘英文求职信
2014/04/13 职场文书
党员廉洁自律个人总结
2015/02/13 职场文书
审查起诉阶段律师意见书
2015/05/19 职场文书
2015年教师党员个人总结
2015/11/24 职场文书
2016优秀员工先进事迹材料
2016/02/25 职场文书
用python开发一款操作MySQL的小工具
2021/05/12 Python
MySQL 查询速度慢的原因
2021/05/25 MySQL
Go语言设计模式之结构型模式
2021/06/22 Golang
Python 处理表格进行成绩排序的操作代码
2021/07/26 Python
Nginx实现会话保持的两种方式
2022/03/18 Servers
使用Java去实现超市会员管理系统
2022/03/18 Java/Android