Mysql主从复制和读写分离(图文)

一、MySQL主从复制与读写分离

案例概述:在实际的生产环境中,如果对数据库的读和写都在同一个数据库服务器中操作,无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。因此,一般来说 都是通过主从复制(Master-Slave)**来同步数据,再通过**读写分离来提升数据库并发负载能力的方案来进行部署与实施

二、MySQL 主从复制原理

MySQL 的主从复制和 MySQL 的读写分离两者有着紧密联系,首先要部署主从复制,
只有主从复制完成了,才能在此基础上进行数据的读写分离。

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

如上图所示
主mysql服务器在数据库里做记录更改,都会写入自己的二级制日志中,从mysql服务器发现主服务器数据库进行记录更改就会打开自己的I/O线程请求连接主服务器,主服务器这时会打开dump线程同意从服务器的请求然后将记录发送给从服务器,从服务器将记录写入自己的中继日志中,然后打开sql线程,将中继日志中的操作记录执行写入自己的服务器数据库中,至此复制完成。

三、MySQL读写分离原理

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

  1. 读写分离存在意义
  • 因为数据库的“写”(写10000条数据可能要3分钟)操作是比较耗时的。
  • 但是数据库的“读”(读10000条数据可能只要5秒钟)。
  • 所以读写分离,解决的是,数据库的写入,影响了查询的效率。
  1. 常见的 MySQL 读写分离分为两种

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

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

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

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

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

四、Mysql主从复制实验

环境配置

主机

操作系统

IP地址

Master

CentOS7

192.168.86.10

Slave1

CentOS7

192.168.86.20

Slave2

CentOS7

192.168.86.30

  1. Mysql主从服务器时间同步

#如果系统不是最小化安装的话应该都是默认安装好的,这里不再进行演示

  1. 主服务器的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.86.%' IDENTIFIED BY '123456';			#给从服务器授权
FLUSH PRIVILEGES;

show master status;

#File 列显示日志名,Fosition 列显示偏移量

spring 主从读写分离 某个方法读取主库 mysql主从 读写分离_数据库

spring 主从读写分离 某个方法读取主库 mysql主从 读写分离_服务器_02

  1. 从服务器的mysql配置(2台)
vim /etc/my.cnf
server-id = 2						#修改,注意id与Master的不同,两个Slave的id也要不同
relay-log=relay-log-bin						#添加,开启中继日志,从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index		#添加,定义中继日志文件的位置和名称

systemctl restart mysqld

mysql -u root -p
change master to master_host='192.168.86.10' , master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=603;
				#配置同步,注意 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进程


spring 主从读写分离 某个方法读取主库 mysql主从 读写分离_mysql_03

spring 主从读写分离 某个方法读取主库 mysql主从 读写分离_数据库_04

一般 Slave_IO_Running: No 的可能性:
1、网络不通
2、my.cnf配置有问题
3、密码、file文件名、pos偏移量不对
4、防火墙没有关闭

  1. 验证主从复制效果

主服务器上创建一个新数据库db_test

spring 主从读写分离 某个方法读取主库 mysql主从 读写分离_数据库_05

从服务器上查看有无数据库db_test

spring 主从读写分离 某个方法读取主库 mysql主从 读写分离_数据库_06

spring 主从读写分离 某个方法读取主库 mysql主从 读写分离_数据库_07

验证完成