MySQL主从复制与读写分离
1.MySQL主从复制原理
就是基于二进制日志进行数据同步的。
(1)主从复制的作用
(1)实现读写分离
(2)跨主机热备份数据
(3)作为数据库高可用性的基础
(2)主从复制的分类
(1)statement 基于语句的复制
优点:执行效率高,占用空间小;
缺点:无法保证在高并发负载时候的精确度。
(2)row 基于行的复制
优点:精确度高
缺点:执行效率低,占用空间大
(3)mixed 混合类型的复制
默认采用基于语句的复制,一旦发现基于语句无法保证精确复制时,就会采用基于行的复制
2.主从复制的过程
关键词:两个日志,三个线程
1)主库(master)如果发生数据更新,会将写入操作记录到二进制日志(bin log)里
2)从库(slave)探测到主库的二进制日志发生了更新,就会开启IO线程向主库请求二进制日志事件
3)主库会为每个从库IO线程的请求开启DUMP线程,并发送二进制日志事件给从库
4)从库接收到二进制日志事件后会保存到自己的中继日志(relay log)中
附:在半同步模式下从库会返回确认信息给主库,主库会用ack收集线程接收从库反馈的确认信息(5.7版本开始支持)
5)从库还会开启SQL线程读取中继日志里的事件,并在本地重放(将中继日志事件解析成sql语句逐一执行),从而实现主库和从库的数据一致
(1)主从复制的配置步骤
1)主从服务器先做时间同步
2)修改主从数据库的配置文件,主库开启二进制日志,从库开启中继日志
3)在主库创建主从复制的用户,并授予主从复制的权限
4)在从库使用 change master to
对接主库,并 start slave
开启同步
5)在从库使用 show slave status\G
查看 IO线程和 SQL线程的状态是否都为 YES
时间同步
##选配项
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的磁盘同步指令,将缓冲区数据刷新到磁盘
#"双1设置"适合数据安全性要求非常高,而且磁盘IO写能力足够支持的业务,比如订单、交易、充值、支付消费系统。"双1模式"下,当磁盘IO无法满足业务需求时,比如11.11活动的压力。推荐一下性能较快的设置,并使用带蓄电池后备电源,防止系统断电异常。
innodb_flush_log_at_trx_commit=2 #每次事务提交时MySQL都会把日志缓存区的数据写入日志文件中,但是并不会同时刷新到磁盘上。该模式下,MySQL会每秒执行一次刷新磁盘操作
sync_binlog=500 #在进行500次事务提交以后,Mysql将执行一次fsync的磁盘同步指令,将缓冲区数据刷新到磁盘
##选配项
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 从库上开启该功能,建议开启。
注:一般 Slave_IO_Running: No 的可能性:
1、网络不通
2、my.cnf配置有问题
3、密码、file文件名、pos偏移量不对
4、防火墙没有关闭
(2)主从复制的同步模式
1)异步复制:主库在执行完客户端提交的事务后就会立即响应给客户端
2)半同步复制:主库在执行完客户端提交的事务后,只要等待一个从库返回响应给主库,才会响应给客户端
3)全同步复制:主库在执行完客户端提交的事务后,要等待所有从库返回都响应给主库,才会响应给客户端
半同步复制:
##查看半同步是否在运行
#主数据库执行
show status like 'Rpl_semi_sync_master_status';
show variables like 'rpl_semi_sync_master_timeout';
#从数据库执行(此时可能还是OFF状态,需要在下一步重启IO线程后,从库半同步状态才会为ON)
show status like 'Rpl_semi_sync_slave_status';
#重启从数据库上的IO线程
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;
#在主库查询半同步状态
show status like '%Rpl_semi%';
3.常见问题
(1)在什么情况下半同步复制会降为异步复制?
当主库在半同步复制超时时间内(rpl_semi_sync_master_timeout)没有收到从库的响应,就会自动降为异步复制。
当主库发送完一个事务事件后,主库在超时时间内收到了从库的响应,就会又恢复为半同步复制。
(2)主从复制延迟问题?
根本原因:主库可以并发多线程执行写入操作,而从库的SQL线程默认是单线程串行化复制,从库的复制效率可能会跟不上主库的写入速度
(3)如何判断发生了主从复制延迟?
通过在从库执行show slave status\G命令,查看输出的Seconds_Behind_Master参数的值来判断,是否有发生主从延时。如果为正值表示主从已经出现延时,数字越大表示从库落后主库越多。
(4)导致主从复制延迟有哪些因素?
1)主库写入操作并发量太大
2)网络延迟
3)从库硬件比主库差
4)使用了同步复制
5)慢SQL语句过多
(5)延迟的解决
1)网络方面:将从库分布在相同局域网内或网络延迟较小的环境中。
2)硬件方面:从库配置更好的硬件(CPU 内存 固态硬盘),提升随机写的性能。
3)配置方面:sync_binlog=0 innodb_flush_log_at_trx_commit=2
由于从库不需要这么高的数据安全性,所以不使用 双1设置
logs-slave-updates=0
从库同步的事件不记录到从库自身的二进制日志中
innodb_buffer_pool_size=物理内存的80%
加大innodb引擎缓存池大小,让更多数据读写在内存中完成,减少磁盘的IO压力
4)架构方面:主从复制的同步模式采用 异步复制 或 半同步复制 或 并行复制;采用读写分离架构
5)操作方面:将大事务拆分为多个较小的事务;优化 DDL 操作,合并多个 DDL 操作为一个批处理操作
(6)主从复制不一致问题的解决
1)先进入主库,进行锁表,防止数据写入
flush tables with read lock;
set gloabl read_only=1;
2)进行数据全量备份
mysqldump -u root -p密码 库名 表名 > XXX.sql
3)使用scp命令把备份文件传到从库机器,进行数据恢复
scp XXX.sql 从库IP:目录/
stop slave;
mysql -u root -p密码 < XXX.sql
4)使用 change master to
重新做主从复制
change master to master_host='主库IP', master_port=3306, master_user='用户名', master_password='密码', master_log_file='二进制文件', master_log_pos=二进制事件位置;
附:二进制文件和二进制事件位置需要在主库查询 show master status;
start slave;
5)主库解锁
unlock tables;
set gloabl read_only=0;
4.读写分离的原理和作用
在主库上处理事务性操作(写入操作),在从库上处理查询操作(读操作),再通过主从复制将主库上的数据同步给从库。
作用:通过读写分离可以分担数据库单节点的负载压力,提高数据库的读写性能
Amoeba 基于是 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,高版本不建议使用。
systemctl disable --now firewalld
setenforce 0
vim /etc/selinux/config
disabled
rpm -qa | grep jdk
yum remove java*
java -version
cd /opt/
ls
rm -rf rh
ls
rz -E 上传amoeba-mysql-binary-2.2.0.tar.gz jdk-6u14-linux-x64.bin
chmod +x jdk-6u14-linux-x64.bin
./jdk-6u14-linux-x64.bin ##按yes,按enter
ls
mv jdk1.6.0_14/ /usr/local/
mkdir /usr/local/amoeba
tar xf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
cd /usr/local/
ls
ls jdk1.6.0_14/
ls amoeba/
ls amoeba/bin/
vim /etc/profile.d/jdk1.6.sh
export JAVA_HOME=/usr/local/jdk1.6.0_14
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$AMOEBA_HOME/bin
source /etc/profile
echo $PATH
java -version
cd /usr/local/amoeba/bin
./amoeba
cd ..
ls
cd conf/
ls
cp amoeba.xml{,.bak}
ls
vim amoeba.xml
cp dbServers.xml{,.bak}
ls
vim dbServers.xml
cd ..
ls
cd bin/
ls
./amoeba start & #启动Amoeba软件,按ctrl+c 返回/usr/local/amoeba/bin/amoeba
netstat -anpt | grep 8066 #查看8066端口是否开启,默认端口
主从库
create user 'amoeba'@'20.0.0.%' identified by 'amoeba123';
grant all on *.* to 'amoeba'@'20.0.0.%';
amoeba
20.0.0.170
xlb
abc123