mysql的主从复制和读写分离:
主从复制
面试必问:主从复制的原理
主从复制的模式:
1、mysql的默认模式:
异步模式 主库在更新完事务之后会立即把结果返回给从服务器,并不关心从库是否接受到,以及从库是否处理成功。
网络问题可能没有同步,或者是其他因素的影响导致同步失败。
快 效率高
2、全同步模式:
主库在更新完事务之后,立即把结果返回到从库,所有的从库执行完毕之后才能继续下一个同步。安全,但是性能低。
3、半同步复制
介乎于异步和全同步之间,主库更新完事务之后,也是同步到从库。同步完成之后有一个等待时间
等待时间是一个tcp/ip的往返时间
5毫秒左右
既在一定程度上保证了效率,也在一定程度上保证了数据的完整性。
主从复制的延迟怎么解决:
1、网络问题,防火墙的原因
2、硬件设备问题,cpu、内存和磁盘出了问题
3、配置文件写错了。
配置文件当中进行设置的方式提高数据的安全性。
数据库的存储引擎要是innodb
双一设置:
innodb_flush_log_at_trx_commit=1
每次提交都会刷新事务日志,确保事务的持久性。但是会影响性能。
sync_binlog=1
每次提交事务,将二进制日志的内容保存到磁盘,确保日志的持久性。提高了安全性。
性能化设置:
sync_binlog=N(5或者10)
最多提交几次事务会进行磁盘刷新,日志内容保存到磁盘
innodb_flush_log_at_trx_commit=2
保存在内存中,不进行刷新。(不推荐)
innodb_buffer_pool_size=60m
可以控制innodb存储引擎缓冲池的大小,增大可以提高数据库的性能,但是占用的是系统内存,配置的时候注意合理化时间。
主从复制如何实现:
实现是基于mysql的二进制日志,根据主库的二进制文件的标准位,实现主和从的同步。
主从服务器之间,服务器的时间要同步。
架构:
三台服务器
192.168.60.91 mysql 8.0 主
192.168.60.92 mysql 8.0 从
192.168.60.93 mysql 8.0 从
主:
1、
yum -y install ntpdate
2、查看三台机器的时间是否相同,不相同使用以下命令
ntpdate ntp.aliyun.com
3、更改mysql的配置文件/etc/my.cof
server-id = 1 log-bin=master-bin binlog_format=MIXED log-slave-updates=true #允许从服务器从主库复制数据时可以写入从库自己的二进制日志中去
4、创建主的用户
mysql> CREATE USER 'myslave'@'192.168.60.%' IDENTIFIED WITH mysql_native_password BY '123456'; mysql> GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.60.%'; mysql> FLUSH PRIVILEGES;
show master status;
从服务器
1、更改从的配置文件
server-id = 2 #主和从的id不能一样,从和从的id也不能一样 relay-log=relay-log-bin #从服务器上获取二进制日志的开头,开启从库的二进制日志 relay-log-index=slave-relave-bin.index #二进制日志的索引文件的名称 relay_log_recovery=1 #配置从服务器在启动时是否执行二进制日志的恢复操作(和主库同步),1表示开启。
2、创建从的用户并刷新
mysql> CREATE USER 'myslave'@'192.168.60.%' IDENTIFIED WITH mysql_native_password BY '123456'; mysql> GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.60.%'; mysql> FLUSH PRIVILEGES;
3、
CHANGE master to master_host='192.168.60.91',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=855; start slave;
4、查看
show slave status\G;
Slave_l0_Running: Yes 从库和主机的读写通信是否正常 Slave SQL Running: Yes slave mysgl进程状态是否正常,
读写分离,MHA
主从的架构中,主库只负责写,从库只负责读。
读写分离的方式:
1、代码实现 开发人员纯靠代码完成,涉及到数据库的二次开发,性能好,不需要额外的硬件设备
2、中间层代理 代理服务器。在客户端和主从架构之间有一个代理服务器。代理服务器收到客户端的请求之后,通过客户端的sql语句进行判断,读转到从,写转到主。
Amoeba:读写分离最常见的客户端代理软件。java代码开发的一个软件。
192.168.60.91 mysql 8.0 主
192.168.60.92 mysql 8.0 从
192.168.60.93 mysql 8.0 从
192.168.60.30 jdk1.6 Amoeba 代理服务器
192.168.60.40 mysql maridb 客户端
操作:
1、安装java环境
[root@test3 opt]# ls amoeba-mysql-binary-2.2.0.tar.gz nginx-1.22.0 jdk-6u14-linux-x64.bin nginx-1.22.0.tar.gz [root@test3 opt]# cp jdk-6u14-linux-x64.bin /usr/local/ [root@test3 opt]# cd /usr/local/ [root@test3 local]# chmod +x jdk-6u14-linux-x64.bin [root@test3 local]#./jdk-6u14-linux-x64.bin //按yes,按enter
2、将java环境的目录改个名字
[root@test3 local]#mv jdk1.6.0_14/ /usr/local/jdk1.6
3、增加java的环境变量
[root@test3 local]# 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 [root@test3 local]# source /etc/profile #重启配置文件
4、查看java的版本
[root@test3 local]# java -version java version "1.6.0_14"
5、安装Amoeba软件
[root@test3 local]# mkdir /usr/local/amoeba [root@test3 local]# cd /opt/ [root@test3 opt]# tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/ [root@test3 opt]# chmod -R 755 /usr/local/amoeba/ [root@test3 opt]# /usr/local/amoeba/bin/amoeba amoeba start|stop #显示这个就说明安装成功
6、在主的mysql上开发权限给Amoeba访问
CREATE USER 'amoeba'@'192.168.60.%' IDENTIFIED WITH mysql_native_password BY '123456'; GRANT REPLICATION SLAVE ON *.* TO 'amoeba'@'192.168.60.%'; GRANT ALL PRIVILEGES ON *.* TO 'amoeba'@'192.168.60.%'; flush privileges;
7、配置代理服务器的amoeba服务,更改配置文件amoeba.xml:
[root[root@test3 conf]# cp amoeba.xml amoeba.xml.bak [root@test3 conf]# cp amoeba.xml amoeba.xml.bak #备份配置文件 [root@test3 conf]# vim amoeba.xml 30 <property name="user">amoeba</property> 32 <property name="password">123456</property> 115 <property name="defaultPool">master</property> --117-去掉注释- 118 <property name="writePool">master</property> 119 <property name="readPool">slaves</property>
8、更改配置文件dbServers.xml
[root@test3 conf]# cp dbServers.xml dbServers.xml.bak [root@test3 conf]# vim dbServers.xml --23行--注释掉 作用:默认进入test库 以防mysql中没有test库时,会报错 <!-- <property name="schema">test</property> --> 26 <property name="user">amoeba</property> 28 <!-- mysql password --> 29 <property name="password">123456</property> 45 <dbServer name="master" parent="abstractServer"> 48 <property name="ipAddress">192.168.60.91</property> 52 <dbServer name="slave1" parent="abstractServer"> 55 <property name="ipAddress">192.168.60.92</property> #复制上面6行粘贴,设置从服务器2的名slave2和地址 58 <dbServer name="slave2" parent="abstractServer"> 59 <factoryConfig> 60 <!-- mysql ip --> 61 <property name="ipAddress">192.168.60.93</property> 62 </factoryConfig> 63 </dbServer> 65 <dbServer name="slaves" virtual="true"> 71 <property name="poolNames">slave1,slave2</property>
9、查看端口是否起来
[root@test3 conf]# netstat -anpt | grep java tcp6 0 0 127.0.0.1:36918 :::* LISTEN 20767/java tcp6 0 0 :::8066 :::* LISTEN 20767/java tcp6 0 0 192.168.60.30:58678 192.168.60.91:3306 ESTABLISHED 20767/java tcp6 0 0 192.168.60.30:43590 192.168.60.93:3306 ESTABLISHED 20767/java tcp6 0 0 192.168.60.30:42896 192.168.60.92:3306 ESTABLISHED 20767/java
10、在客户端上安装mariadb-server mariadb
[root@test4 ~]# yum install -y mariadb-server mariadb [root@test4 ~]# systemctl start mariadb.service
11、在主从上开启查询日志
[root@mysql1 ~]# vim /etc/my.cnf general_log=ON general_log_file=/usr/local/mysql/data/mysql_general.log
12、在客户端服务器上测试:
mysql -u amoeba -p123456 -h 192.168.60.30 -P8066 MySQL [(none)]> use xy102; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed MySQL [xy102]> create table test (id int(10),name varchar(10),address varchar(20)); Query OK, 0 rows affected, 1 warning (0.02 sec) MySQL [xy102]> insert into test values('1','zhangsan','this_is_slave1'); Query OK, 1 row affected (0.01 sec) MySQL [xy102]> select * from test; +------+----------+----------------+ | id | name | address | +------+----------+----------------+ | 1 | zhangsan | this_is_slave1 | +------+----------+----------------+ 1 row in set (0.02 sec) MySQL [xy102]> select * from test; +------+----------+----------------+ | id | name | address | +------+----------+----------------+ | 1 | zhangsan | this_is_slave1 | +------+----------+----------------+ 1 row in set (0.01 sec) #查询的时候两个从轮流转换(负载均衡)
总结+面试题
1、主从同步复制原理 2、读写分离你们使用什么方式? amoeba 代理 mycat 代码 sql_proxy 通过amoeba代理服务器,实现只在主服务器上写,只在从服务器上读; 主数据库处理事务性查询,从数据库处理select 查询; 数据库复制被用来把事务查询导致的变更同步的集群中的从数据库
3、如何查看主从同步状态是否成功 在从服务器上内输入 show slave status\G 查看主从信息查看里面有IO线程的状态信息,还有master服务器的IP地址、端口事务开始号。 当 Slave_IO_Running和Slave_SQL_Running都是YES时 ,表示主从同步状态成功
4、如果I/O不是yes呢,你如何排查? 首先排查网络问题,使用ping 命令查看从服务器是否能与主服务器通信 再查看防火墙和核心防护是否关闭(增强功能) 接着查看从服务slave是否开启 两个从服务器的server-id 是否相同导致只能连接一台 master_log_file master_log_pos的值跟master值是否一致
5、show slave status能看到哪些信息(比较重要) IO线程的状态信息 master服务器的IP地址、端口、事务开始的位置 最近一次的错误信息和错误位置 最近一次的I/O报错信息和ID 最近一次的SQL报错信息和id
6、主从复制慢(延迟)会有哪些可能?怎么解决? 主服务器的负载过大,被多个睡眠或 僵尸线程占用 导致系统负载过大,从库硬件比主库差,导致复制延迟 主从复制单线程,如果主库写作并发太大,来不及传送到从库,就会到导致延迟 慢sql语句过多 网络延迟
mysql主从复制
若主从版本不一致,从的版本一定要高于主,保证可以向下兼容 因为若主的版本更新,低版本的从无法兼容的。