详解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 相关文章推荐
MySQL 使用SQL语句修改表名的实现
Apr 07 MySQL
详解mysql三值逻辑与NULL
May 19 MySQL
MySQL系列之十一 日志记录
Jul 02 MySQL
一篇文章带你深入了解Mysql触发器
Aug 02 MySQL
MySQL之select、distinct、limit的使用
Nov 11 MySQL
MySQL窗口函数的具体使用
Nov 17 MySQL
Linux7.6二进制安装Mysql8.0.27详细操作步骤
Nov 27 MySQL
将MySQL的表数据全量导入clichhouse库中
Mar 21 MySQL
SQL语句多表联合查询的方法示例
Apr 18 MySQL
MYSQL事务的隔离级别与MVCC
May 25 MySQL
delete in子查询不走索引问题分析
Jul 07 MySQL
MySQL常用慢查询分析工具详解
Aug 14 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
php+dojo 的数据库保存拖动布局的一个方法dojo 这里下载
2007/03/07 PHP
php中的MVC模式运用技巧
2007/05/03 PHP
Ping服务的php实现方法,让网站快速被收录
2012/02/04 PHP
PHP基于imap获取邮件实例
2014/11/11 PHP
PIGCMS 如何关闭聊天机器人
2015/02/12 PHP
功能强大的PHP发邮件类
2016/08/29 PHP
基于jQuery实现表格数据的动态添加与统计的代码
2011/01/31 Javascript
jQuery源码分析-05异步队列 Deferred 使用介绍
2011/11/14 Javascript
JS 实现图片直接下载示例代码
2013/07/22 Javascript
javascript history对象(历史记录)使用方法(实现浏览器前进后退)
2014/01/07 Javascript
jquery实现垂直和水平菜单导航栏
2020/08/27 Javascript
JS检测数组类型的方法小结
2017/03/14 Javascript
解决循环中setTimeout执行顺序的问题
2018/06/20 Javascript
vue进入页面时滚动条始终在底部代码实例
2019/03/26 Javascript
JavaScript变量作用域及内存问题实例分析
2019/06/10 Javascript
JavaScript如何判断input数据类型
2020/02/06 Javascript
vue css 引入asstes中的图片无法显示的四种解决方法
2020/03/16 Javascript
[03:05]《我与DAC》之xiao8:DAC与BG
2018/03/27 DOTA
Python实现单词翻译功能
2017/06/06 Python
对python中的logger模块全面讲解
2018/04/28 Python
Python读取本地文件并解析网页元素的方法
2018/05/21 Python
世界排名第一的万圣节服装店:Spirit Halloween
2018/10/16 全球购物
介绍一下mysql的日期和时间函数
2013/03/28 面试题
材料化学应届生求职信
2013/10/09 职场文书
运动会表扬稿大全
2014/01/16 职场文书
市场营销管理制度
2014/01/29 职场文书
统计系教授推荐信
2014/02/28 职场文书
财产公证书
2014/04/10 职场文书
环卫工人节活动总结
2014/08/29 职场文书
银行党的群众路线教育实践活动对照检查材料
2014/09/25 职场文书
村支部书记群众路线对照检查材料思想汇报
2014/10/08 职场文书
就业导师推荐信范文
2015/03/27 职场文书
2015年幼师工作总结
2015/04/28 职场文书
退休欢送会主持词
2015/07/01 职场文书
详解盒子端CSS动画性能提升
2021/05/24 HTML / CSS
基于docker安装zabbix的详细教程
2022/06/05 Servers