主从复制
主从复制,修改,表里的数据:主mysql上的数据,新增都会同步到从mysql上
面试题:
mysql的主从复制的模式:
1、异步复制:mysql的默认复制就是异步复制。只要执行完之后,客户端提交事务,主的mysql会立即把结果返回给从服务器,主mysql并不关心从mysql是否已经接受,并且处理
主一旦崩溃,主mysql的事务可能没有传到从mysql,这时侯强行把从提升为主,可能把新的主mysql数据不完整。(很少见,工作中异步复制)
异步:类似于udp。只管发送,不管有没有收到
2、全同步复制:主库执行完成一个事务,所有的从库都执行了该事务之后才会返回客户端。
因为需要等待所有从库全部执行完成,性能必然下降。(对数据一致性,和数据库完整要求很好的场景)
3、半同步复制:介于异步复制和同步复制之间。主库执行完一个客户端提交的事务之后, 至少等待一个从库接受并处理完成之后才会返回给客户端。半同步在-定程度上提高了数据的安全性。也会有一定的延迟。最好在低延时使用。
这个延迟一般是一个tcp/ip的往返时间。 (从发 送到接收的时间,单位是毫秒)
时间<1ms : round-trip time RTT
面试问题
主从复制延迟问题:
1、网络延迟
2、主从硬件设备(CPU主频、内存io、硬件io)。
3、同步复制而不是异步复制。
解决方案:
1、硬件方面: 主库一般来说不需要动的太多,从库的硬件配置要更好。提升随机写的性能。硬盘可以考虑换成固态的,升级cpu的核数,扩展一下内存。尽量使用物理机(不要用云服务器)
2、网络层面:主从服务器配置在一个局域网内,尽量避免跨网段跨机房
3、架构方面:做读写分离,把写入控制在主库,从库负责读,降低主库的压力
4、配置方面:mysql配置。从配置文件的角度实现性能最大化追求安全性的配置
innodb_flush_log_at_trx_commit=1
1默认就是每次事务提交时都会刷新事务日志。已确保持久性,最高级别的数安全性,但是会影响性能
0就是事务提交时不会立刻刷新,而是每秒刷新一次。可以提高性能,但是发生故障会导致数据丢失。
2事务提交时,事务日志不会写入硬盘,而是保存到系统缓存,不会进行刷新。一定的安全性和性能。内存要求比较高。
sync_binlog=1
1也就是默认值,每次提交事务之后,直接把二进制日志刷新到磁盘,以确保日志的持久性。占用较高性能。但安全性高。
0进制日志写入到缓存,也不会刷新日志。故障发生也会丢失数据,内存的要求也提高了
3每三个事务执行一次刷新到磁盘。提高性能,但是一旦崩溃,数据会大量丢失。
logs-slave-updates=0
从库的更新不会写入二进制日志。(不建议)
innodb_buffer_pool_size 300M 500G
innodb存储引擎的缓冲池大小,设置的s数值越高,可以提高innodb的性能
更多的数据和索引都可以缓存在内存中。减少磁盘的访问次数。 对系统内存
主从复制的工作过程:
1、主节点的数据记录发生变化都会记录在二进制日志
2、slave节点会一定时间内对主库二进制日志文件进行探测,看其是否发生变化?有变化,从数据库会开启一个I/0的线程请求的主库的二进制事件
3、主库会给每一个I/0的线程启动一个dump,用于发送二进制事件给从库,从库通过IO线程获得更新,slave_sql复制将更新写入到从库本地,实现主从一致。
主从复制的问题:
1、只能在主库上发生变化,然后同步到从。
2、复制过程是串行化过程,在从库上复制是串行的,主库的并行更新不能在从库上并行操作。
3、核心意义:实现读写分离,主库上写,从库上查,实现高可用
读写分离:
实现读写分离,必须基于主从复制
读写分离: 所有的写入操作都在主库,从库只负责读。(select)。如果有更新,是从主库复制到从库。
为什么要有读写分离:
1、数据库在写入数据时,比较耗时
2、数据库在读的时候,速度很快(读10000条,4.96s)
读写分离之后,数据的读取和写入是分开的,哪怕写入的数据量大,但是不影响查询的效率。
在什么场景下需要读写分离??????
数据库不是一定需要读写分离的。只有在某些程序在使用数据库过程中,更新少,但是查询较多,在这种情况下考虑分析,读和查的需求差不多,也可以考虑读写分离。
生产库一般都会做读写分离
测试库一般不管
在工作中,数据库的读写不会在同一个库中完成。即不安全,也可以满足高可用,也可以满足高可用,也不能实现高并发。工作中都会做读写分离。
mysql读写分离的原理
1、根据脚本实现。在代码中实现路由分类。select insert进行路由分类。这种方式是最多的。
性能:在代码中就可以实现,不需要额外的硬件设备
缺点:开发实现的,跟我们无关。如果大型复杂的应用,设计改动代码非常多。
2、基于中间代理层实现
1、mysal-proxy自带的开源项日,基于自带的lua脚本。这些lua脚本不是现成的,要自己写,不熟悉他的内置变量写不出来
2、atlas 360内部做自己使用的代理工具。每天的读写请求承载量可以到几十亿条。支持事务,主持存储过程。
3、Amoeba 陈思儒,之前在阿里就职。是由iava开发的一个开源团建。不支持事务,也不支持存储过程。但是Amoeba还是用的做多的,功能比较强大的软件。实现读写分离
实验:
架构主从复制和读写分离:
mysql-1 主 192.168.10.102
mysql-2 从 192.168.10.100
mysql-3 从 192.168.10.101
mysql-1 主 192.168.10.102
1、主从共同操作
systemctl stop firewalld
setenforce 0
yum -y install ntp
2、主
vim /etc/ntp.conf
--------
server 127.127.10.0
fudge 127.127.10.0 stratum 8
--------
systemctl restart ntpd
vim /etc/my.cnf
-------
log-bin=master-bin
binlog_format = MIXED
log-slave-updates=true
-------
systemctl restart mysqld
mysql -u root -p123456
在mysql里
------------
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.10.%' IDENTIFIED BY '123456';
FLUSH PRIVILEGES;
show master status;
------------
server 127.127.10.0
#设置本地是时钟源,注意修改网段 例如:本地网段为192.168.233.10 则写为:127.127.233.0
fudge 127.127.10.0 stratum 8
#数字越小,时间精确度越高,设置fudge 8 时间层级是8 最高到15
mysql-2 从 192.168.10.100
mysql-3 从 192.168.10.101
systemctl restart ntpd
contrab -e
------
*/30 * * * * /usr/sbin/ntpdate 192.168.10.102
------
systemctl restart mysqld
vim /etc/my.cnf
----------
server-id = 1 #修改,注意id与Master的不同,两个Slave的id也要不同
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
relay_log_recovery = 1
----------
systemctl restart mysqld
mysql -u root -p123456
在数据库中
CHANGE master to master_host='192.168.10.102',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=603;
#配置同步,注意 master_log_file 和 master_log_pos 的值要与Master查询的一致
start slave; #启动同步,如有报错执行 reset slave;
show slave status\G; #查看 Slave 状态
//确保 IO 和 SQL 线程都是 Yes,代表同步正常。
Slave_IO_Running: Yes #负责与主机的io通信
Slave_SQL_Running: Yes #负责自己的slave mysql进程
relay-log=relay-log-bin:
指定了从服务器上中继日志的基本文件名。在这个例子中,
中继日志的文件名将以 "relay-log-bin" 开头。
relay-log-index=slave-relay-bin.index:
指定了中继日志索引文件的名称。中继日志索引文件用于记录中继日志文件的顺序和位置。
在这个例子中,索引文件名为 "slave-relay-bin.index"。
relay_log_recovery=1:
用于配置从服务器在启动时是否执行中继日志的恢复操作。设置为 1 表示启用中继日志的恢复,
通常在从服务器出现异常或崩溃后重启时使用。
这有助于确保从服务器能够从主服务器的二进制日志中正确地读取和应用中继日志,以保持数据一致性
#默认是0, 1开启中继日志的护肤。从服务器出现异常或者崩溃时,从服务器会从主服务器的二进制日志的争取读取和应用中继日志
Amoeba服务器配置
代理服务器 192.168.10.20
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软件
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说明安装成功
在主从上操作
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.10.%' IDENTIFIED BY '123456';
flush privileges;
#再回到amoeba服务器配置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">123456</property>
--115行--
<property name="defaultPool">master</property>
--117-去掉注释-
<property name="writePool">master</property>
<property name="readPool">slaves</property>
*****************************************************************************
cp dbServers.xml dbServers.xml.bak
vim dbServers.xml #修改数据库配置文件
******************************************************************
--23行--注释掉 作用:默认进入test库 以防mysql中没有test库时,会报错
<!-- <property name="schema">test</property> -->
--26--修改
<property name="user">amoeba</property>
--28-30--去掉注释
<property name="password">123456</property>
--45--修改,设置主服务器的名Master
<dbServer name="master" parent="abstractServer">
--48--修改,设置主服务器的地址
<property name="ipAddress">192.168.233.21</property>
--52--修改,设置从服务器的名slave1
<dbServer name="slave1" parent="abstractServer">
--55--修改,设置从服务器1的地址
<property name="ipAddress">192.168.233.22</property>
--58--复制上面6行粘贴,设置从服务器2的名slave2和地址
<dbServer name="slave2" parent="abstractServer">
<property name="ipAddress">192.168.233.23</property>
--65行--修改
<dbServer name="slaves" virtual="true">
--72行--修改
<property name="poolNames">slave1,slave2</property>
********************************************************************************
/usr/local/amoeba/bin/amoeba start & #启动Amoeba软件,按ctrl+c 返回
netstat -anpt | grep java #查看8066端口是否开启,默认端口为TCP 8066
测试读写分离
yum install -y epel-release.noarch
yum install -y mariadb-server mariadb
systemctl start mariadb.service
#在主从服务器上开启查询日志
general_log=ON
general_log_file=/usr/local/mysql/data/mysql_general.log
在客户端服务器上测试:
mysql -u amoeba -p123456 -h 192.168.233.10 -P8066
主从复制是单向的,只能从主复制到从
如果Slave_IO_Running:no 排查思路是什么?
答:85%配置文件问题。
show slave status\G 能看到的信息有哪些呢
1、 I/O和sql的线程状态信息
2、 master服务器的ip地址、端口、事务开始的位置
3、 最近一次的错误信息和错误的位置
4、 最近一次的I/O报错的信息
5、 最近一次sql的报错信息