MySQL数据库--主从复制读写分离
Posted 可乐卷儿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL数据库--主从复制读写分离相关的知识,希望对你有一定的参考价值。
文章目录
一、主从复制
1、原理
- 主从复制的核心:2个日志、3个线程
- 二进制通过哪种方式写入日志(基于行、基于sql、基于混合)
- master线程:bin-log二进制日志、dump线程
- master上的dump线程会监控binlog二进制日志的更新,若有更新会通知slave的I/O线程
- slave:relay-log中继日志、I/O线程、sql线程
- 线程1:
- slave上的I/O线程会向master申请同步bin-log二进制日志的更新内容
- slave的I/O线程把更新内容写入自己的中继日志
- 线程2:
- slave的sql线程把日志中的更新语句同步执行到内容
已达到和master数据库趋于一致
- slave的sql线程把日志中的更新语句同步执行到内容
- 线程1:
2、二进制日志的保存方式
- STATEMENT(基于SQL语句):
- 每一条涉及到被修改的sql 都会记录在binlog中
- 缺点:日志量过大,如sleep()函数,last_insert_id()>,以及user-defined fuctions(udf)、主从复制等架构记录日志时会出现问题
- ROW(基于行)
- 只记录变动的记录,不记录sql的上下文环境
- 缺点:如果遇到update…set…where true 那么binlog的数据量会越来越大
- MIXED 推荐使用
- 一般的语句使用statement,函数使用ROW方式存储
3、主从复制策略
- 全同步:master请求服务时,等待slave全部同步之后才会回应client端
- 半同步:master请求服务时,只要任意一个slave同步
- 异步:master请求服务时,只要master同步即回应请求,不管slave的状态;默认的状态
因为主从复制的默认策略是异步,导致的结果就是主从二进制日志和中继日志的保存内存会越来越大
4、搭建mysql主从复制
- 实验准备(虚拟机):
虚拟机角色 | ip |
---|---|
mysql-master | 192.168.35.40 |
mysql-slave1 | 192.168.35.10 |
mysql-slave2 | 192.168.35.20 |
- 主从服务器时间同步
三台服务器配置
yum install -y ntp ##安装ntp软件
ntpdate ntp.aliyun.com ##时间同步
ntpdate 192.168.35.40 ##把三台服务器同步同一时间,ip为master
crontab -e
*/10 * * * * /usr/sbin/ntpdate 192.168.35.40 ##master和slave1、slave2同步阿里云时钟服务
- 三台服务器安装mysql
此处就不再详细描述,看之前文字LNMP即可
MySQL安装完成确认下是否有mysql用户
- msater服务器开启二进制日志
vim /etc/my.cnf
[mysqld]
server-id = 1 ##主服务器id不可重复;标识服务器的角色
log-bin=master-bin ##开启二进制日志文件
log_slave_updates=ture ##开启从服务器日志同步,允许从从服务器的更新节点过来
systemctl restart mysqld ##重启服务
- master配置:给从服务器提权grant;用于主从对接
mysql -u root -p
grant replication slave on *.* to 'myslave'@'192.168.35.%' identified by '123';##给从服务器提权,允许使用slave的身份复制msater所有数据库的所有表,并制定密码为123
flush privileges;
show master status; ##查询数据库状态
以上可见产生了master- bin.000001日志文件,定位为603
从服务器需要定位到此处进行复制
mysqlbinlog --no-defaults --base64-output=decode-rows -v master-bin.000001 ##查看二进制日志
6. slave1:开启从服务器功能
vim /etc/my.cnf
server-id = 2 ##设置server_id为2,slave2为3
log-bin=master-bin ##开启二进制日志文件
relay-log=relay-log-bin ##从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index ##定义relay_log的位置和名称(index索引)
--->wq保存
systemctl restart mysqld
--------------------->slave1数据库操作<---------------------
change master to master_host='192.168.35.40',master_user='myslave',master_password='123',master_log_file='master-bin.000001',master_log_pos=603;
start slave;
show slave status\\G ##查看主从服务是否成功
- 通用的方法开启slave2的从服务功能
vim /etc/my.cnf
server-id = 3 ##设置server_id为3,slave1为2
log-bin=master-bin ##开启二进制日志文件
relay-log=relay-log-bin ##从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index ##定义relay_log的位置和名称(index索引)
--->wq保存
change master to master_host='192.168.35.40',master_user='myslave',master_password='123',master_log_file='master-bin.000001',master_log_pos=603;
mysql> start slave;
mysql> show slave status\\G ##查看主从服务是否成功
若查询主从是否同步时显示:connecting,可以稍等一会再重新查看
- 测试主从复制
主服务器上创建一个数据库
slave1:已同步
slave2:已同步
若是在slave1服务器上面更改,master主服务器与slave2并没有同步更改
二、读写分离
1、原理
读写分离就是只在主服务器上写,只在从服务器上读
基本的原理是让主数据库处理事务性查询,
而从数据库处理select查询。数据库复制被用来把主数据库上事务性查询导致的变更同步到集群中的从数据库
2、读写分离
因为数据库的“写”(写10000条数据可能要3分钟)操作是比较耗时的。
但是数据库的“读”(读10000条数据可能只要5秒钟)。
所以读写分离,解决的是,数据库的写入,影响了查询的效率
3、读写分离的好处
- 数据库不一定要读写分离,如果程序使用数据库较多时,而更新少,查询多的情况下会考虑使用。
- 利用数据库主从同步,再通过读写分离可以分担数据库压力,提高性能
4、实现方式
常见的MySQL读写分离分为以下两种:
- 基于程序代码内部实现
在代码中根据select、insert 进行路由分类,这类方法也是目前生产环境应用最广泛的。
优点是性能较好,因为在程序代码中实现,不需要增加额外的设备为硬件开支;
缺点是需要开发人员来实现,运维人员无从下手。
但是并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的Java应用,如果在程
序代码中实现读写分离对代码改动就较大。 - 基于中间代理层实现
代理一般位于客户端和服务器之间,代理服务器接到客户端请求后通过判断后转发到后端数据库;
有以下代表性程序:- MySQL-Proxy:MySQL-Proxy 为MySQL开源项目,通过其自带的lua脚本(脚本语言)进 行SQL判断。
- Atlas:由奇虎360的Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它是在mysql-proxy0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。支持事物以及存储过程。
- Amoeba:由陈思儒开发,作者曾就职于阿里巴巴。该程序由Java语言进行开发,阿里巴巴将其用于生产环境。但是它不支持事务和存储过程。
4.1、Amoeba简介
- Amoeba: 是一 个以MySQL为底层数据存储,并对应提供MySQL协议接口的proxy(代理),外号变形虫
- 读取请求发送给从服务器是,采用轮询调度算法
- amoeba使用的java语言编写,配置文件为xml
- amoeba主要负责对外的一个代理IP
- 访问这个IP时,发送的请求为“写"请求,则会转给主服务器
- 当发送的请求为“读"时,会通过调度转发给从服务器,使用轮询算法,轮流分配给两台从服务器
- amoeba可以视为调度器,如果主服务器挂掉(单点故障),则会有MHA解决这个问题
五、搭建MySQL读写分离
1、实验准备
角色 | ip |
---|---|
客户端client(测试) | 192.168.35.50 |
mysql-master | 192.168.35.40 |
mysql-slave1 | 192.168.35.10 |
mysql-slave2 | 192.168.35.20 |
mysql-amoeb | 192.168.35.30 |
2、amoeba(192.168.35.30)安装
- 安装java环境,安装jdk(因为amoeba是基于jdk1.5开发的,所以官方推荐使用jkd1.5/jdk1.6,高版本不建议使用)
将amoeba-mysql-binary-2.2.0.tar.gz和jdk-6u14-linux-x64.bin上传到opt目录下
[root@amoeba opt]# cp jdk-6u14-linux-x64.bin /usr/local/
[root@amoeba opt]# chmod +x jdk-6u14-linux-x64.bin
[root@amoeba opt]# ./jdk-6u14-linux-x64.bin ##enter往下翻页--yes--enter
mv jdk1.6.0_14/ /usr/local/jdk1.6 ##重命名为了便于环境变量的设置
vim /etc/profile
unset i
unset -f pathmunge
export JAVA_HOME=/usr/local/jdk1.6 ##指定jdk的位置
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 ##amoeba文件的位置
export PATH=$PATH:$AMOEBA_HOME/bin ##调用家目录识别amoeba的bin文件
source /etc/profile
java -version
- 安装amoeba软件
mkdir /usr/local/amoeba
tar zxvf 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
3、配置amoeba读写分离,两个slave读负载均衡
在master、slave1、slave2的mysql上开放权限给amoeba
grant all on *.* to test @'192.168.35.%' identified by '123456';
4、修改amoeba主配置文件和数据库文件
配置amoeba服务
cp amoeba.xml amoeba.xml.bak ##备份amoeba的主配置文件
vim amoeba.xml ##修改主配置文件,即配置第三个账户(客户端找amoeba的用户身份)
30 <property name="user">amoeba</property> ##root改为amoeba;修改账户名(这里是client访问amoeba服务器时使用的账号)
32 <property name="password">123123</property> ##修改账户密码(这里是数据库访问amoeba服务器时使用账号时用的密码)
115 <property name="defaultPool">master</property> ##修改默认池
117 取消注释/,取消下面的注释符号-->,改到这里
118 <property name="writePool">master</property>
119 <property name="readPool">slaves</property>
cp dbServers.xml dbServers.xml.bak ##备份数据库配置文件
vim dbServers. xml ##修改数据库配置文件
23 <property name="schema">mysql</property> ##将text修改为mysql;Mysql所有数据库信息( show databases )
26 <property name="user">test</property> ##amoeba访 问三台mysql数据库的账户和密码(账户为test)
29 <property name="password">123456</property> ##取消注释,修改访问数据库的密码
45 <dbServer name="master" parent="abstractServer"> ##修改数据库主服务器名/地址
48 <property name="ipAddress">192.168.35.40</property> ##修改master服务器ip
52 <dbServer name="slave1" parent="abstractServer"> ##修改从服务器名slave1
55 <property name="ipAddress">192.168.35.10</property> ##修改从服务器地址
紧接复制52-57行,粘贴,添加第二台服务器名
59 <dbServer name="slave2" parent="abstractServer"> ##修改从服务器名为slave2
62 <property name="ipAddress">192.168.35.20</property> ##修改第二台服务器IP
66 <dbServer name="slaves" virtual="true">
这时可以复制会话另开一个页面查看一下配置文件(因为amoeba需要一直开启才能查询到端口)
vim amoeba.xml
cd /usr/local/amoeba/conf/amoeba.xml ##查询发现端口是8806
netstat -antp | grep 8806
5、 开启amoeba
/usr/local/amoeba/bin/amoeba start
netstat -antp | grep 8806
6、客户端远程登录amoeba
yum -y install mariadb ##下载mariadb客户端;mairadb比MySQL更轻量级的版本
mysql -uamoeba -p123123 -h 192.168.35.30 -P8066 ##远程登录amoeba服务器;amoeba会做代理,所以指向的地址是amoeba的ip的端口8066
mariadb的作用:
提供命令库
提供连接数据的驱动
提供tcp的端口3306
7、测试
- 测试一
client端远程访问amoeba的地址,并进入数据库创建新的数据库,验证master和slaves是否同步
client端进入数据库创建表aa,发现master+slave1+slave2已同步创建数据表aa
- 测试二:
测试mysql的读写分离,2台从服务器关闭主从同步,在客户端数据库的数据表内插入数据验证amoeba读写分离
stop slave ##2台从服务器关闭主从同步
show slave status\\G ##查询从服务器的状态;已是NO
use zyt ##client进入数据库
insert into aa values(1); ##client端插入数据
master处理写的任务,可以查询到数据表aa
从服务器处理读的任务,查询看不到数据
3. 测试三:
在从服务器上更改表数据,使用客户端验证从服务器读,和轮询的方式读
insert into aa values(2); ##slave1插入数据
insert into aa values(3); ##slave2插入数据
MySQL [player]> select * from test; ##client端查询验证轮询
以上是关于MySQL数据库--主从复制读写分离的主要内容,如果未能解决你的问题,请参考以下文章
MySQL 主从复制与读写分离(原理深刻,过程详细,值得一看)