详解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 相关文章推荐
SQL注入的实现以及防范示例详解
Jun 02 MySQL
详细谈谈MYSQL中的COLLATE是什么
Jun 11 MySQL
MySql子查询IN的执行和优化的实现
Aug 02 MySQL
MySQL 数据类型详情
Nov 11 MySQL
MySQL之select、distinct、limit的使用
Nov 11 MySQL
Mysql分库分表之后主键处理的几种方法
Feb 15 MySQL
MySQL数据库完全卸载的方法
Mar 03 MySQL
利用JuiceFS使MySQL 备份验证性能提升 10 倍
Mar 17 MySQL
MySQL创建管理KEY分区
Apr 13 MySQL
MySQL 表锁定 LOCK和UNLOCK TABLES的 SQL语法
Apr 18 MySQL
MySQL数据库事务的四大特性
Apr 20 MySQL
优化Mysql查询的示例
Apr 26 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
ajax在joomla中的原生态应用代码
2012/07/19 PHP
使用PHP遍历文件目录与清除目录中文件的实现详解
2013/06/24 PHP
php函数与传递参数实例分析
2014/11/15 PHP
PHP跨平台获取服务器IP地址自定义函数分享
2014/12/29 PHP
PHP模板引擎Smarty中变量的使用方法示例
2016/04/11 PHP
Laravel框架FormRequest中重写错误处理的方法
2019/02/18 PHP
Cookie 注入是怎样产生的
2009/04/08 Javascript
5款Javascript颜色选择器
2009/10/25 Javascript
一个简单的js动画效果代码
2010/07/20 Javascript
关于JavaScript中var声明变量作用域的推断
2010/12/16 Javascript
JavaScript实现选择框按比例拖拉缩放的方法
2015/08/04 Javascript
浅谈bootstrap源码分析之tab(选项卡)
2016/06/06 Javascript
Wireshark基本介绍和学习TCP三次握手
2016/08/15 Javascript
jQuery属性选择器用法示例
2016/09/09 Javascript
jQuery ajax MD5实现用户注册即时验证功能
2016/10/11 Javascript
vue 自定义全局方法,在组件里面的使用介绍
2018/02/28 Javascript
layui实现table加载的示例代码
2018/08/14 Javascript
js核心基础之构造函数constructor用法实例分析
2019/05/11 Javascript
这应该是最详细的响应式系统讲解了
2019/07/22 Javascript
Nodejs封装类似express框架的路由实例详解
2020/01/05 NodeJs
Vue初始化中的选项合并之initInternalComponent详解
2020/06/11 Javascript
js实现点击烟花特效
2020/10/14 Javascript
[01:36:17]DOTA2-DPC中国联赛 正赛 Ehome vs iG BO3 第一场 1月31日
2021/03/11 DOTA
Python3调用微信企业号API发送文本消息代码示例
2017/11/10 Python
python实现requests发送/上传多个文件的示例
2018/06/04 Python
python统计中文字符数量的两种方法
2019/01/31 Python
django 链接多个数据库 并使用原生sql实现
2020/03/28 Python
解决Jupyter notebook更换主题工具栏被隐藏及添加目录生成插件问题
2020/04/20 Python
Python控制台实现交互式环境执行
2020/06/09 Python
如何在windows下安装配置python工具Ulipad
2020/10/27 Python
利用html5 file api读取本地文件示例(如图片、PDF等)
2018/03/07 HTML / CSS
HTML5 input placeholder 颜色修改示例
2014/05/30 HTML / CSS
微信小程序之html5 canvas绘图并保存到系统相册
2019/06/20 HTML / CSS
为什么会有内存对齐
2016/10/10 面试题
小学生考试获奖感言
2014/01/30 职场文书
男方婚礼答谢词
2015/01/20 职场文书