主从复制
作用:
1.做数据的热备,作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。
2.架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能。
3.读写分离,使数据库能支撑更大的并发。
1--在从服务器可以执行查询工作(即我们常说的读功能),降低主服务器压力;(主库写,从库读,降压)。
2--在从服务器进行备份,避免备份期间影响主服务器服务;(确保数据安全)。
基于binlog的主从复制搭建
步骤
1.准备环境
提前准备三台搭建了MySQL以及关闭防火墙的linux,并保证三台MySQL起始数据一致,实战中最好是新的mysql,方便操作,如果无法新建需使用数据备份方式将数据库数据恢复一致
2.数据库中创建并授权有主从复制权限账户
mysql> grant replication slave,reload,super on *.* to 'testslave'@'%' identified by '111111';
mysql> flush privileges;
#注意:生产环境中密码采用高级别的密码,实际生产环境中将'%'换成具体的ip
#注意:该用户理论上只需要主库存在,从库不需要创建,但在实战中,由于各种突发情况从库随时有可能升级为主库,所以所有从库也要创建replication slave:拥有此权限可以查看从服务器,从主服务器读取二进制日志。
super权限:允许用户使用修改全局变量的SET语句以及CHANGE MASTER语句
reload权限:必须拥有reload权限,才可以执行flush [tables | logs | privileges]
3.主库的配置
修改数据库配置文件 /etc/my.cnf
保证主库以下两点
1.binlog日志功能打开
2.拥有server-id,并且在该主从复制集群中唯一
重启数据库
#进入主库查看当前主库状态
mysql> show master status\G
# 注意:此次查询关注file和position两条信息,从库配置时使用
4.从库的配置
修改数据库配置文件 /etc/my.cnf
保证从库有唯一的server-id
重启数据库
#如有错可嫩需要执行
#chown -R mysql:mysql /opt/mxl
进入从库
#查看从库当前监听主库状态
mysql> show slave status\G
Empty set (0.00 sec) #默认未开启监听
# 执行如下命令
mysql> CHANGE MASTER TO
MASTER_HOST='192.168.88.120', #主库ip
MASTER_USER='testslave', #主库用户名
MASTER_PASSWORD='111111', #主库密码
MASTER_LOG_FILE='a.000003', #主库配置文件
MASTER_LOG_POS=427; #主库日志偏移量#如有错可嫩需要执行
#chown -R mysql:mysql /opt/mxl# 开启监听
mysql> start slave;uuid位置 /opt/chengpf/data/mysql/auto.cnf
#查看从库当前监听主库状态
mysql> show slave status\G
5.其余从库做相同配置
6.配置完成后查看主从复制是否实现
原理
Mysql的主从复制中主要有三个线程:
master(binlog dump thread)、slave(I/O thread 、SQL thread)
,Master一条线程和Slave中的两条线程。
master(binlog dump thread)
主要负责Master库中有数据更新的时候,会按照binlog
格式,将更新的事件类型写入到主库的binlog
文件中。并且,Master会创建log dump
线程通知Slave主库中存在数据更新,这就是为什么主库的binlog日志一定要开启的原因。
I/O thread
线程在Slave中创建,该线程用于请求Master,Master会返回binlog的名称以及当前数据更新的位置、binlog文件位置的副本。然后,将binlog
保存在 「relay log(中继日志)」 中,中继日志也是记录数据更新的信息。
SQL thread
也是在Slave中创建的,当Slave检测到中继日志有更新,就会将更新的内容同步到Slave数据库中,这样就保证了主从的数据的同步。
总结:
步骤一:主库db的更新事件(update、insert、delete)被写到binlog
步骤二:从库发起连接,连接到主库
步骤三:此时主库创建一个binlog dump thread线程,把binlog的内容发送到从库
步骤四:从库启动之后,创建一个I/O线程,读取主库传过来的binlog内容并写入到relay log.
步骤五:从库还会创建一个SQL线程,从relay log里面读取内容,将更新内容写入到slave的db.
# 查看线程
mysql> SHOW PROCESSLIST\G
基于GTID的主从复制搭建
全局事务标识:global transaction identifiers(GTID)
是用来代替传统复制的方法,GTID复制与普通复制模式的最大不同就是不需要指定二进制文 件名和位置。
事务
事务是数据库为保证SQL操作完整性而提供的一种机制。保证一个业务对应的多条SQL要么 同时成功,要么同时失败。
事务的ACID
Atomicity 原子性 保证多条SQL要么同时成功,要么同时失败。
Consistency 一致性 事务执行前后,数据的状态是一致的。
Isolation 隔离性 并发访问相同数据时,不同用户是否可以看到另外一个用户未提交的数据。oracle默认只能看到提交后的。
Durability 持久性 一个事务一旦提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响 。
步骤
-
准备三台mysql机器环境,并且创建mysql并赋予权限,同上
-
主库配置
修改数据库配置文件 /etc/my.cnf
保证以下四点
log-bin=/opt/liuyh/log #定义server id master必写
server-id=111 #开启binlog日志,master必写
gtid_mode=ON #开启gtid
enforce_gtid_consistency=1 #强制gtid重启数据库
3.从库配置
修改数据库配置文件 /etc/my.cnf
server-id=112
gtid_mode=ON
enforce_gtid_consistency=1重启数据库
#进入从库
mysql> stop slave; #停止数据库监听
Query OK, 0 rows affected (0.01 sec)#设置从库监听信息
mysql> change master to
master_host='192.168.157.121', #主ip 地址 最好用域名
master_user='testslave', #主服务上面创建的用户
master_password='111111',
master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.00 sec)# 开启监听
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)# 查看从库监听状态
mysql> show slave status\G
4.其余从库做相同配置
5.查看主从复制状态
MyCat读写分离
在主从数据库集群架构中,让主库负责处理写入操作,而从库只负责处理select查询,让两者分工明确达到提高数据库整体读写性能。当然,主数据库另外一个功能就是负责将数据变更同步到从库中,也就是写操作
优点
1. 分摊服务器压力,提高机器的系统处理效率。
2. 在写入不变,大大分摊了读取,提高了系统性能。另外,当读取被分摊后,又间接提高了写入的性能。所以,总体性能提高了。
3. 增加冗余,提高服务可用性,当一台数据库服务器宕机后可以调整另外一台从库以最快速度恢复服务。
常用的读写分离中间件
MyCAT 是使用 JAVA 语言进行编写开发,使用前需要先安装 JAVA 运行环境(JRE),由于 MyCAT 中使用了 JDK7 中的一些特性,所以要求必须在 JDK7 以上的版本上运行。
部署
1.准备一台虚拟机
2.安装java环境
[root@localhost tmp]# cd /tmp
[root@localhost tmp]# rpm -ivh jdk-8u251-linux-x64.rpm
此时:JDK已经被安装在了 /usr/java/jdk1.80_xxx
目录下。
3.配置环境变量
[root@localhost java]# vi /etc/profile
在profile中尾部追加一下3行配置
export JAVA_HOME=/usr/java/default
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=.//刷新环境变量
[root@localhost java]# source /etc/profile
4.解压缩Mycat.tar.gz
[root@localhost opt]# tar zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz -C /opt/
5.配置环境变量
[root@localhost opt]# vi /etc/profile
export MYCAT_HOME=/opt/mycat
export PATH=$PATH:$JAVA_HOME/bin:$MYCAT_HOME/bin
//刷新环境变量
[root@localhost java]# source /etc/profile
6.修改mycat配置文件
-
server.xml
# 进入mycat/conf目录中
[root@mycat conf]# vim server.xml
...
<!--下面的用户和密码是应用程序连接到 MyCat其中的schemas 配置项所对应的值是逻辑数据库的名字,可以*定义,但需要和后面 schema.xml 文件中配置的一致。-->
<user name="root" defaultAccount="true">
<property name="password">root</property>
<property name="schemas">mycatdb</property>
</user>
<!--
<!--下面是另一个用户,并且设置的访问 TESTED 逻辑数据库的权限是 只读。可以注释掉
<user name="user">
<property name="password">user</property>
<property name="schemas">mycatdb</property>
<property name="readOnly">true</property>
</user>
-->
</mycat:server>
2.schema.xml
逻辑库和分表设置
<schema name="testdb" // 逻辑库名称,与server.xml的一致
checkSQLschema="false" // 不检查sql
sqlMaxLimit="100" // 最大连接数
dataNode="dn1"> // 数据节点名称
<!--这里定义的是分表的信息-->
</schema>
数据节点
<dataNode name="dn1" // 此数据节点的名称
dataHost="localhost1" // 主机组虚拟的
database="testdb" /> // 真实的数据库名称
主机组
<dataHost name="localhost1" // 主机组
maxCon="1000" minCon="10" // 连接
balance="0" // 负载均衡
writeType="0" // 写模式配置
dbType="mysql" dbDriver="native" // 数据库配置
switchType="1" slaveThreshold="100">
<!--这里可以配置关于这个主机组的成员信息,和针对这些主机的健康检查语句-->
</dataHost>
balance 属性
负载均衡类型,目前的取值有 3 种:
1. balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的 writeHost 上。
2. balance="1", 全部的 readHost 与 writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且 M1 与 M2 互为主备),正常情况下,M2,S1,S2 都参与 select 语句的负载均衡。
3. balance="2", 所有读操作都随机的在 writeHost、readhost 上分发。
4. balance="3", 所有读请求随机的分发到 wiriterHost 对应的 readhost 执行,writerHost 不负担读压力, #注意 balance=3 只在 1.4 及其以后版本有,1.3 没有。
writeType 属性
负载均衡类型
1. writeType="0", 所有写操作发送到配置的第一个 writeHost,第一个挂了切换到还生存的第二个writeHost,重新启动后已切换后的为准.
2. writeType="1",所有写操作都随机的发送到配置的 writeHost,#版本1.5 以后废弃不推荐。
健康检查
<heartbeat>select user()</heartbeat> #对后端数据进行检测,执行一个sql语句,user()内部函数
读写配置
<writeHost host="hostM1" url="192.168.246.135:3306" user="mycat" password="Qf@12345!">
<!-- can have multi read hosts -->
<readHost host="hostS2" url="192.168.246.136:3306" user="mycat" password="Qf@12345!" />
</writeHost>
以下是配置范例
[root@mycat conf]# vim schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="mycatdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="localhost1" database="back" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="192.168.157.111" url="192.168.157.111:3306" user="mycat" password="111111">
<!-- can have multi read hosts -->
<readHost host="192.168.157.112" url=192.168.157.112:3306" user="mycat" password="111111" />
<readHost host="192.168.157.113" url=192.168.157.113:3306" user="mycat" password="111111" />
</writeHost>
</dataHost>
</mycat:schema>
7.创建用户
在上述schema.xml中配置了主库从库的登录用户,若库中没有该用户,需要创建
mysql> grant all on back.* to mycat@'%' identified by '111111';
8.启动mycat
[root@localhost conf]# mycat start
Starting Mycat-server...
9.登录mycat测试