一,主从复制

1.原理

主从复制原理:
首先主库发送更新事件到从库;
然后从库读取更新记录,并执行更新记录;
最后使得从库的内容与主库保持一致。

2.复制类型

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

3.工作流程

1) Master 服务器保存记录到二进制日志
每个事务更新数据完成之前,Master服务器在二进制日志(Binary log)记录变更的数据,写入二进制日志完成后,Master服务器通知存储引擎提交事务;

2) Slave服务器复制Master服务器的日志
SLAVE节点会开启I/o线程,用于监听master的二进制日志的更新,一旦发生更新内容,则向master的dump线程发出同步请求;
master的dump线程在接收到SLAVE的I/o请求后,会读取二进制日志文件中更新的数据,并发送给slave的I/o线程;
SLAVE的I/o线程接收到数据后,Slave服务器将Master服务器的二进制日志复制到其中继日志;

3) Slave服务器重放复制过来的日志
SQL slave thread处理该过程的最后一步,SQL线程从中继日志读取事件,并重放其中的事件而更新Slave服务器的数据,使其与Master服务器中的数据一致。

核心部分:
二个日志:二进制日志和中继日志
三个线程: master的dump和slave的I/O,SQL.

二,读写分离

1.原理

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

2.读写分离存在的意义

因为数据库的“写”(写10000条数据可能要3分钟)操作是比较耗时的。
但是数据库的“读”(读10000条数据可能只要5秒钟)。
所以读写分离,解决的是:数据库的写入,影响了查询的效率。

3.使用场景

数据库不一定要读写分离,如果程序使用数据库较多时,而更新少,查询(select)多的情况下会考虑使用。
利用数据库主从同步,再通过读写分离可以分担数据库压力,提高性能。

4.常见的mysql读写分离

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

2.基于中间代理层实现
代理一般位于客户端和服务器之间,代理服务器接到客户端请求后通过判断后转发到后端数据库,有以下代表性程序。
(1)MySQL-Proxy。MySQL-Proxy 为 MySQL 开源项目,通过其自带的 lua脚本进行SQL 判断。
(2)Atlas是由奇虎360的Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。
它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。
360内部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。支持事物以及存储过程。
(3)Amoeba:由陈思儒开发,作者曾就职于阿里巴巴。该程序由Java语言进行开发,阿里巴巴将其用于生产环境。但是它不支持事务和存储过程。
Amoeba:是一个以MySql为底层数据存储,并对应提供MySQL协议接口的proxy(代理),外号变形虫,读取请求发送给从服务器,并采用轮询调度算法
amoeba使用的java语言编写,配置文件为xml,
amoeba主要负责对外的一个代理IP,
访问这个IP时,发送的请求为“写”请求,则会转给主服务器
当发送的请求为“读”时,会通过调度转发给从服务器,使用轮询算法,轮流分配给两台从服务器。

三,主从复制配置

实验环境:
master服务器:192.168.118.11
slave1服务器:192.168.118.13
slave2服务器:192.168.118.14
amoeba服务器:192.168.118.128
client:192.168.118.132

1.master服务器配置

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.118.%' identified by '123456';
flush privileges;

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

2.从服务器slave配置

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

mysql -u root -p
#配置同步,注意 master_log_file 和 master_log_pos 的值要与Master查询的一致,
change master to master_host='192.168.118.11' , master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=604;

start slave;					#启动同步,如有报错执行 reset slave;
show slave status\G				#查看 Slave 状态
//确保 IO 和 SQL 线程都是 Yes,代表同步正常。
Slave_IO_Running: Yes			#负责与主机的io通信
Slave_SQL_Running: Yes			#负责自己的slave mysql进程

Slave_IO_Running: No 的可能性:
网络不通;
防火墙没有关闭;
my.cnf配置有误;
密码、file文件名、position偏移量与master不符。

3.验证(主服务器创建,从服务器查看)

四,读写分离配置

1.安装JAVA环境

Amoeba服务器配置

cd /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/local/jdk1.6

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

source /etc/profile
java -version

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 说明安装成功

3.主从服务器授权

在Master、Slave1、Slave2 的mysql上开放权限给 Amoeba 访问
grant all on *.* to 'test'@'192.168.118.%' identified by '123456';

4.配置amoeba读写分离

(1)修改amoeba配置文件
cd /usr/local/amoeba/conf/
cp amoeba.xml amoeba.xml.bak
vim amoeba.xml           #修改amoeba配置文件

#30行修改
<property name="user">amoeba</property>
#32行修改
<property name="password">123</property>
#115行修改
<property name="defaultPool">master</property>
#117行去掉注释
<property name="writePool">master</property>
<property name="readPool">slaves</property>

(2)修改数据库配置文件
cp dbServers.xml dbServers.xml.bak

vim dbServers.xml
#23行注释掉
作用:默认进入test库 以防mysql中没有test库时,会报错
<!-- mysql schema
<property name="schema">test</property>
-->
#26行修改
<!-- mysql user -->
<property name="user">test</property>
#---------28-30去掉注释----------------------------------
<property name="password">123456</property>
#---------45修改,设置主服务器的名Master------------------
<dbServer name="master"  parent="abstractServer">
#---------48修改,设置主服务器的地址----------------------
<property name="ipAddress">192.168.118.11</property>
#---------52修改,设置从服务器的名slave1-----------------
<dbServer name="slave1"  parent="abstractServer">
#---------55修改,设置从服务器1的地址---------------------
<property name="ipAddress">192.168.118.13</property>
#---------58复制上面6行粘贴,设置从服务器2的名slave2和地址---
<dbServer name="slave2"  parent="abstractServer">
<property name="ipAddress">192.168.118.14</property>
#---------修改后的65或66修改-------------------------------------
<dbServer name="slaves" virtual="true">
#---------71修改----------------------------------------
<property name="poolNames">slave1,slave2</property>

/usr/local/amoeba/bin/amoeba start&	 
netstat -anpt | grep java		#查看8066端口是否开启,默认端口为TCP 8066
netstat -anpt | grep 8066


5.测试

client上测试:
安装MySQL虚拟客户端
yum -y install mysql mysql-server

登录AMOEBA代理服务器:
mysql -u amoeba -p123 -h 192.168.118.128 -P8066

在master主服务器上
use ceshi;
create table test (id int(10),name varchar(10),address varchar(20));

两台从服务器上
stop slave;			#关闭同步
use test;

在slave1上
insert into test values('1','slave1','this_is_slave1');
在slave2上
insert into test values('2','slave2','this_is_slave2');
在master主服务器上
insert into test values('3','master','this_is_master');

主服务器上:



客户端上:

主服务器上:

从服务器开启同步:


client上:

总结

mysql主从复制,slave角色复制master角色的数据,以此来保证数据的完整性;
主从复制里二进制日志与中继日志是为了:区分master与slave的关系;
通过amoeba代理服务器,实现只在主服务器上写,只在从服务上读,主数据库处理事务性查询,从数据库处理 select 查询;
主从复制主要是为了解决mysql单点故障,没有冗余备份的问题;
读写分离主要是为了解决mysql的I/O读写压力不均衡的问题。
主从复制慢(延迟)有哪些可能:
网络延迟;
慢SQL语句过多;
从库硬件比主库差,导致复制延迟;
主服务器的负载过大,被多个睡眠或者僵尸线程占用,导致系统负载过大;
主从复制单线程,如果主库写并发太大,来不及传送到从库,就会导致延迟;
posted on 2022-12-05 09:48  知趣。  阅读(34)  评论(0编辑  收藏  举报