目录
1.概念
什么是读写分离
为什么要读写分离
什么时候要读写分离
主从复制与读写分离
mysql支持的复制类型
主从复制的工作过程
MySQL读写分离原理
目前较为常见的 MySQL 读写分离分为以下两种
1.基于程序代码内部实现
2.基于中间代理层实现
2.搭建MySQL主从复制
Mysql主从服务器时间同步
主服务器设置
从服务器同时设置
主服务器的mysql配置
同时配置从服务器的mysql
验证主从复制效果
3.MySQL主从复制的同步模式
异步复制(Asynchronous replication)
全同步复制(Fully synchronous replication)
半同步复制(Semisynchronous replication)
半同步复制配置
主数据库配置
从数据库配置
查看半同步是否在运行
主数据库执行
从数据库执行
在主库查询半同步状态
4.搭建 MySQL读写分离
Amoeba服务器配置
安装Java环境
安装Amoeba软件
配置 Amoeba读写分离,两个Slave读负载均衡
配置amoeba服务
测试读写分离
在客户端服务器上测试
在主服务器上
在两台从服务器上
最后在客户端服务器上
5.MySQL主从复制延迟
注:
代理一般位于客户端和服务器之间,代理服务器接到客户端请求后通过判断后转发到后端数据库,有以下代表性程序。
由于使用MySQL Proxy 需要写大量的Lua脚本,这些Lua并不是现成的,而是需要自己去写。这对于并不熟悉MySQL Proxy 内置变量和MySQL Protocol 的人来说是非常困难的。
Amoeba是一个非常容易使用、可移植性非常强的软件。因此它在生产环境中被广泛应用于数据库的代理层。
实验准备:
Master 服务器:192.168.88.22 mysql5.7
Slave1 服务器:192.168.88.40 mysql5.7
Slave2 服务器:192.168.88.13 mysql5.7
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
yum install ntp -y
vim /etc/ntp.conf
--末尾添加--
server 127.127.88.0 #设置本地是时钟源,注意修改网段
fudge 127.127.88.0 stratum 8 #设置时间层级为8(限制在15内)
service ntpd start
yum install ntp ntpdate -y
systemctl start ntpd
/usr/sbin/ntpdate 192.168.88.22 #进行时间同步
crontab -e
*/30 * * * * /usr/sbin/ntpdate 192.168.88.22
vim /etc/my.cnf
server-id=1
log-bin=mysql-bin #添加,主服务器开启二进制日志
binlog_format=mixed
#选配项
expire_logs_days=7 #设置二进制日志文件过期时间,默认值为0,表示logs不过期
max_binlog_size=500M #设置二进制日志限制大小,如果超出给定值,日志就会发生滚动,默认值是1GB
skip_slave_start=1 #阻止从库崩溃后自动启动复制,崩溃后再自动复制可能会导致数据不一致的
#"双1设置",数据写入最安全
innodb_flush_log_at_trx_commit=1
#redo log(事务日志)的刷盘策略,每次事务提交时MySQL都会把事务日志缓存区的数据写入日志文件中,并且刷新到磁盘中,该模式为系统默认
sync_binlog=1
#在进行每1次事务提交(写入二进制日志)以后,Mysql将执行一次fsync的磁盘同步指令,将缓冲区数据刷新到磁盘
systemctl restart mysqld
mysql -u root
grant replication slave on *.* to 'myslave'@'192.168.88.%' identified by '123';
#给从服务器授权
flush privileges;
show master status;
vim /etc/my.cnf
server-id = 2 #修改,注意id与Master的不同,两个Slave的id也要不同
relay-log=relay-log-bin #开启中继日志,从主服务器上同步日志文件记录到本地
relay-log-index=relay-log-bin.index #定义中继日志文件的位置和名称,一般和relay-log在同一目录
选配项
innodb_buffer_pool_size=2048M
#用于缓存数据和索引的内存大小,让更多数据读写内存中完成,减少磁盘操作,可设置为服务器总可用内存的 70-80%
sync_binlog=0
#MySQL不做任何强制性的磁盘刷新指令,而是依赖操作系统来刷新数据到磁盘
innodb_flush_log_at_trx_commit=2
#每次事务log buffer会写入log file,但一秒一次刷新到磁盘
log-slave-updates=0
#slave 从 master 复制的数据会写入二进制日志文件里,从库做为其他从库的主库时设置为 1
relay_log_recovery=1
#当 slave 从库宕机后,假如 relay-log 损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的 relay-log, 并且重新从 master 上获取日志,这样就保证了 relay-log 的完整性。默认情况下该功能是关闭的,将 relay_log_recovery 的值设置为 1 时, 可在 slave 从库上开启该功能,建议开启。
systemctl restart mysqld
mysql -u root
change master to master_host='192.168.88.22',master_user='myslave',master_password='123',master_log_file='mysql-bin.000011',master_log_pos=603;
start slave;
show slave status\G
//确保 IO 和 SQL 线程都是 Yes,代表同步正常。
Slave_IO_Running: Yes #负责与主机的io通信
Slave_SQL_Running: Yes #负责自己的slave mysql进程
#一般 Slave_IO_Running: No 的可能性:
1、网络不通
2、my.cnf配置有问题
3、密码、file文件名、pos偏移量不对
4、防火墙没有关闭
vim /etc/my.cnf #在 [mysqld] 区域添加下面内容
plugin-load=rpl_semi_sync_master=semisync_master.so #加载mysql半同步复制的插件
rpl_semi_sync_master_enabled=ON #或者设置为"1",即开启半同步复制功能
rpl-semi-sync-master-timeout=1000 #超时时间为1000ms,即1s
systemctl restart mysqld
vim /etc/my.cnf
plugin-load=rpl_semi_sync_slave=semisync_slave.so
rpl_semi_sync_slave_enabled=ON
systemctl restart mysqld
show status like 'Rpl_semi_sync_master_status';
show variables like 'rpl_semi_sync_master_timeout';
show status like 'Rpl_semi_sync_slave_status';
stop slave io_thread; #关闭数据库上的IO线程
start salve io_thread; #启动数据库上的IO线程
show status like '%Rpl_semi%';
参数说明:
Rpl_semi_sync_master_clients #半同步复制客户端的个数
Rpl_semi_sync_master_net_avg_wait_time #平均等待时间(默认毫秒)
Rpl_semi_sync_master_net_wait_time #总共等待时间
Rpl_semi_sync_master_net_waits #等待次数
Rpl_semi_sync_master_no_times #关闭半同步复制的次数
Rpl_semi_sync_master_no_tx #表示没有成功接收slave提交的次数
Rpl_semi_sync_master_status #表示当前是异步模式还是半同步模式,on为半同步
Rpl_semi_sync_master_timefunc_failures #调用时间函数失败的次数
Rpl_semi_sync_master_tx_avg_wait_time #事物的平均传输时间
Rpl_semi_sync_master_tx_wait_time #事物的总共传输时间
Rpl_semi_sync_master_tx_waits #事物等待次数
Rpl_semi_sync_master_wait_pos_backtraverse #可以理解为"后来的先到了,而先来的还没有到的次数"
Rpl_semi_sync_master_wait_sessions #当前有多少个session因为slave的回复而造成等待
Rpl_semi_sync_master_yes_tx #成功接受到slave事物回复的次数
注:
实验准备:
Master 服务器:192.168.88.22 mysql5.7
Slave1 服务器:192.168.88.40 mysql5.7
Slave2 服务器:192.168.80.13 mysql5.7
Amoeba 服务器:192.168.88.31 jdk1.6、Amoeba
客户端 服务器:192.168.88.50 mysql
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=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$AMOEBA_HOME/bin
source /etc/profile
java -version
mkdir /usr/local/amoeba
tar xf 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说明安装成功
#先在Master、Slave1、Slave2 的mysql上开放权限给 Amoeba 访问
grant all on *.* to test@'192.168.88.%' identified by 'yy.com';
cd /usr/local/amoeba/conf/
cp amoeba.xml amoeba.xml.bak
vim amoeba.xml #修改amoeba配置文件
##30行##
amoeba
##32行##
123456
##115行##
master
##117-去掉注释-
master
slaves
cp dbServers.xml dbServers.xml.bak
vim dbServers.xml #修改数据库配置文件
##23行##注释掉 作用:默认进入test库 以防mysql中没有test库时,会报错
##26##修改
test
##28-30##去掉注释
123.com
##45##修改,设置主服务器的名Master
##48##修改,设置主服务器的地址
192.168.80.10
##52##修改,设置从服务器的名slave1
##55##修改,设置从服务器1的地址
192.168.80.11
##58##复制上面6行粘贴,设置从服务器2的名slave2和地址
192.168.80.12
##65行##修改
##71行##修改
slave1,slave2
/usr/local/amoeba/bin/amoeba start& #启动Amoeba软件,按ctrl+c 返回
netstat -anpt | grep java #查看8066端口是否开启,默认端口为TCP 8066
yum install -y mariadb-server mariadb
systemctl start mariadb.service
mysql -u amoeba -p123 -h 192.168.88.31 -P8066
#通过amoeba服务器代理访问mysql ,在通过客户端连接mysql后写入的数据只有主服务会记录,然后同步给从--从服务器
use ikun;
create table test (id int(10),name varchar(10),address varchar(20));
stop slave;
use ikun;
##在slave1上
insert into test values('1','zhangsan','this_is_slave1');
##在slave2上
insert into test values('2','lisi','this_is_slave2');
##在主服务器上
insert into test values('3','wangwu','this_is_master');
use ikun;
select * from test;
##客户端会分别向slave1和slave2读取数据,显示的只有在两个从服务器上添加的数据,没有在主服务器上添加的数据
1.master服务器高并发,形成大量事务
2.网络延迟
3.主从硬件设备导致
4.是同步复制、而不是异步复制