MySQL 主从复制和读写分离:
主从复制:主MySQL上的数据,新增,修改库,表,表里的数据,都会同步到从MySQL上。
MySQL的主从复制的模式:(面试题)
1,异步复制:(MySQL的默认复制就是异步复制,最常用。只要执行完之后,客户端提交事务,主MySQL会立即把结果返回给从服务器,主服务器并不关心从服务器是否已经接受,并且处理。)
问题:主一旦崩溃,主MySQL的事务可能没有传到从MySQL,这个时候强行的把从提升为主,可能到新的主服务器数据不完整。(很少见。)
2,全同步复制,主库执行完成一个事务,所有的从库都执行了该事务之后才会返回客户端。
因为需要等待所有从库全部执行完成,性能必然下降。(对数据一致性,和数据完整性要求很好的场景。)
3,半同步复制:介于异步和全同步复制之间。主库执行完一个客户端提交的事务之后,至少等待一个从库接受并处理完成之后才会返回给客户端。半同步在一定程度上提高了数据的安全性。也会有一定延迟。
这个延迟一般是一个tcp/ip的时间:从发送到接受的时间,单位是毫秒ms
时间<1ms: round-trip time RTT
架构:主从复制和读写分离:
mysql1 主
mysql2 从
mysql3 从
test1 读写分离的服务器
test2 客户端
实验:
主从复制
主从服务器之间的时间也要同步:
安装 ntp工具
yum -y install ntp
改ntp配置文件:
数字越小,时间的精确度越高,设置fudge 8 时间层级是8 最高到15。
从本地获取时间源,不从网络获取
从服务器执行同步命令
生成中会加一个定时任务
每30分钟同步一次
查看时间:
改主配置文件:
log-bin=master-bin #添加,主服务器开启二进制日志
binlog_format = MIXED
log-slave-updates=true
#添加,允许slave从master复制数据时可以写入到自己的二进制日志
进入服务器,新建一个用户,并授权:
GRANT REPLICATION SLAVE ON . TO 'myslave'@'192.168.176.%' IDENTIFIED BY '123456';
FLUSH PRIVILEGES;
show master status;
靠位置点进行同步:
修改从数据库配置文件
每个id不能一样:
server-id = 2
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
relay_log_recovery = 1
relay_log_recovery=1
默认是0,1开启中继日志的复制。从服务器出现异常或者崩溃时,从服务器会从主服务器的二进制
server-id = 3
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
relay_log_recovery = 1
重启数据库
从服务器分别进入数据库:
mysql -u root -p123456;
和主进行同步:
CHANGE master to master_host='192.168.176.30',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=604;
启动同步:
start slave;
查看:
show slave status\G;
Slave_IO_Running: Yes #负责与主机的io通信
Slave_SQL_Running: Yes #负责自己的slave mysql进程
在主数据库创建库,表
从库也会跟着改变
面试题:如果slave io running no
1,网络问题
2,my.cnf 配置文件写错了
3,
4,防火墙和安全机制。
主从复制是单向的,只能从主复制到从服务器。
面试题:主从复制的延迟问题:
1,网络延迟
2,主从硬件设备(CPU主频,内存IO,硬件IO)。
3,同步复制而不是异步复制。
解决方案:
1,硬件方面,主库一般来说不需要动的太多,从库硬件配置要更好。提升随机写的性能。硬盘可以换成固态的,升级cpu的核数,扩容内存。尽量使用物理机(不要用云服务器。)4核8G,硬盘。
2,网络层面,主从服务器配置在一个局域网内,尽量避免跨网段和跨机房。
3,架构方面:读写分离,把写入控制在主库,从库负责读,降低从库的压力
4,配置方面 mysql配置。从配置文件的角度实现性能最大化
追求安全性的配置:
innodb_flush_log_at_trx_commit=1
每次事务提交时都会刷新事务日志。已确保持久性,最高级别的数据安全性,但是会响应性能,默认就是1
0就是事务提交时不会立刻刷新,而是每秒刷新一次。可以提高性能,但是发生故障会导致数据丢失。
2 事务提交时,事务日志不会写入硬盘而是保持在系统缓存,不会进行刷新。一定的安全性和性能。内存要求比较高。
sync_binlog=1
1,也是默认值,每次提交事务之后,直接把二进制日志刷新,以确保日志的持久性。占用比较高的性能。但是安全性高。
0,二进制日志写入到缓存,也不会刷新日志。故障发生也会丢失数据,内存的要求也提高了
3,每3个事务执行一次刷新磁盘。提高性能,但是一旦崩溃,数据会大量丢失。
追求性能化:
sync_binlog=0
innodb_flush_log_at_trx_commit=2
logs-slave-updates=0
从库的更新不会写入二进制日志(不建议)
innodb_buffer_pool_size 300M 500G
innodb存储引擎的缓冲池大小,设置的s值越高,可以提高innodb的性能。
更多的数据和索引都可以缓存在内存中。减少磁盘的访问次数。对系统内存要求比较高。
主从复制的一个工作过程:
1,主节点是数据记录发生变化都会记录在二进制日志。
2,slave节点会一定时间内对主库的二进制文件进行探测,看其是否发生变化,如果有变化,从库会开启一个I/O线程,请求主库的二进制事件。
3,主库会给每一个I/O的线程启动一个dump。用于发送二进制事件给从库,从库通过I/O线程获取更新,slave_sql负责将更新写入到从库本地。实现主从一致。
主从复制的问题:
1,只能在主库上发生变化,任何同步到从。
2,复制过程是串行化过程,在从库上复制是串行的,主库的并行更新不能在库上并行操作。
3,主从复制的设计目的就是为在主库上写,在从库上查看。读写分离,实现高可用
mysql主从复制
若主从版本不一致,从的版本一定要高于主,保证可以向下兼容
因为若主的版本更新,低版本的从无法兼容的
读写分离:
要实现读写分离,必须要实现主从复制。
读写分离:所有的写入操作在主库,从库只负责读。(select)。如果有更新,是从主库复制到从库。
为什么要有读写分离:
1,数据库在写入数据时,比较耗时(mysql写一万条数据 3分钟)
2,数据库在读的时候,速度很快(读一万,5秒)
读写一旦分离,数据库的写入和读取是分开的,哪怕写入的数据量比较大,但是不影响查询的效率。
在什么场景下需要读写分离:
只有在某些程序在使用数据库过程中,更新少,但是查询比较多,这种情况可用考虑读写分离。
读和查的需求差不多,也可以考虑读写分离。
生产库一般都会做读写分离
测试库一般不管。
在工作中,数据库的读写不会在同一个库中完成。即不安全,也不能满足高可用,也不能实现高并发。工作中读会做读写分离。
mysql读写分离的原理:
1,根据脚本实现。在代码中实现路由分类。select insert 进行路由分类。这种方式是最多的。
性能好,在代码中可用实现,不需要额外的硬件设备
缺点:开发实现的,跟我们无关。如果大型的复制的应用,设计改动的代码非常多。
2,基于中间代理层实现:
mysql-proxy自带的开源项目,基于自带的lua脚本。这些lua脚本不是现成的,,要自己写,不熟悉他的内置变量写不出来的 atlas 360内部做自己代理工具。每天的读写请求承载量可用到几十亿条。支持事务,支持存储过程。
3,Amoeba 陈思儒,之前在阿里就职。是由java开发的一个开源团建。不支持事务,也不支持存储过程。但是Amoeba还是用的最多的功能比较强大的软件。
实验:
mysql1 主
mysql2 从
mysql3 从
test1 读写分离的服务器 Amooeba
test2 客户端
修改java环境
查看java环境:java -version
基于 jdk1.5开发的,官方推荐的
更换java环境
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
安装amoeba
在opt目录下创建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说明安装成功
在三台数据库给用户amoeba赋权
grant all on *.* to amoeba@'192.168.176.%' identified by '123456';
flush privileges;
在amoeba服务器修改配置文件:
cd /usr/local/amoeba/conf/
配置用户信息:
配置数据库信息:
备份
cp amoeba.xml amoeba.xml.bak
改配用户信息:
vim amoeba.xml
--30行--
amoeba
--32行--
123456
--115行--
master
--117-去掉注释-
master
slaves
修改数据库信息:
cp dbServers.xml dbServers.xml.bak
vim dbServers.xml
--23行--注释掉 作用:默认进入test库 以防mysql中没有test库时,会报错
--26--修改
amoeba
--28-30--去掉注释
123456
--45--修改,设置主服务器的名Master
--48--修改,设置主服务器的地址
192.168.233.21
--52--修改,设置从服务器的名slave1
--55--修改,设置从服务器1的地址
192.168.233.22
--58--复制上面6行粘贴,设置从服务器2的名slave2和地址
192.168.233.23
--65行--修改
--71行--修改
slave1,slave2
启动Amoeba软件:
/usr/local/amoeba/bin/amoeba start &
查看8066端口是否开启
netstat -anpt | grep java
测试读写分离:
客户端安装 mariadb
yum install -y mariadb-server mariadb
systemctl start mariadb.service
修改三台mysql生成日志文件
最后一行添加:
general_log=ON
general_log_file=/usr/local/mysql/data/mysql_general.log
三台库打开日志
tail -f /usr/local/mysql/data/mysql_general.log
在客户端对表进行写入时三个日志都会有显示
查看表只有一台从库有记录,而且会轮询记录: