MySQL使用主从复制与读写分离的原因:
●在企业应用中,成熟的业务通常数据量都比较大
●单台MySQL在安全性、高可用性和高并发方面都无法满足实际的需求
(myisam基于表级锁定;innodb基于行级锁定 --存储引擎不能满足并发读、写的需求)
●配置多台主从数据库服务器以实现读写分离
●MySQL的复制类型
基于语句的复制
基于行的复制
混合类型的复制(语句、行、日志文件)
●MySQL主从复制的工作过程
●只在主服务器上写,只在从服务器上读
●主数据库处理事务性查询,从数据库处理select查询
●数据库复制用于将事务性查询的变更同步到集群中的从数据库
读写分离原理示意图
●需要创建的三种账户:
1.master要创建权限账户(主从复制账户),允许slave能够读取进行复制
2.创建(读写分离账户),在读、写的每一台服务器上都要有
3.客户端访问Amoeba的账户,此账号和数据库没关系
●此架构存在问题:
master是个单节点,一旦宕机就无法写入数据了。
三台装有MySQL5.7版本的服务器,角色分配如下:
master:14.0.0.20
slave01:14.0.0.30
slave02:14.0.0.40
一台Amoeba代理服务器
Amoeba:14.0.0.10
先把服务器的防火墙和核心防护全部关闭。
systemctl stop firewalld.service
setenforce 0
MySQL主服务器配置
1.修改主服务器的主配置文件参数
[root@localhost ~]# vim /etc/my.cnf
[mysqld]
...省略内容
server-id=11 ##MySQL服务器的id,各个服务器之间不能相同
log-bin=master-bin ##主服务器日志文件
log-slave-updates=true ##允许中继日志读取主服务器的二进制日志文件
[root@localhost ~]# systemctl restart mysqld.service
[root@localhost ~]# ls /usr/local/mysql/data/
auto.cnf ib_logfile0 master-bin.000001 performance_schema
ib_buffer_pool ib_logfile1 master-bin.index sys
ibdata1 ibtmp1 mysql
2.登录MySQL主服务器,创建让从服务器同步数据的账号
[root@localhost ~]# mysql -u root -p
mysql> grant replication slave on *.* to 'myslave'@'14.0.0.%' identified by 'abc123';
mysql> flush privileges;
注意:到这一步后不要再在数据库中进行任何操作,否则读取数据的位置会变
MySQL从服务器配置
1.修改从服务器的主配置文件参数
[root@localhost ~]# vim /etc/my.cnf
[mysqld]
...省略内容
server-id=22 ##MySQL服务器的id,需要配置不同数字
relay-log=relay-log-bin ##从主服务器上同步日志文件记录到本地中继日志
relay-log-index=slave-relay-bin.index ##定义中继日志的索引
[root@localhost ~]# systemctl restart mysqld.service
2.登录MySQL从服务器,添加要同步数据的master服务器的账号、二进制日志文件、开始同步的位置(position)
[root@localhost ~]# mysql -u root -p
mysql> change master to master_host='14.0.0.20',master_user='myslave',master_password='abc123',
master_log_file='master-bin.000001',master_log_pos=599;
mysql> start slave; ##启动从服务器
mysql> show slave status\G; ##查看从服务器状态
*************************** 1. row ***************************
Slave_IO_Running: Yes
Slave_SQL_Running: Yes ##IO线程和SQL线程要全部Yes才成功
Amoeba服务器的部署
#关闭防火墙和核心防护
systemctl stop firewalld.service
setenforce 0
1.安装jdk环境
[root@localhost local]# cp jdk-6u14-linux-x64.bin /usr/local/
[root@localhost local]# chmod +x jdk-6u14-linux-x64.bin
[root@localhost local]# ./jdk-6u14-linux-x64.bin
yes
按enter
[root@localhost local]# mv jdk1.6.0_14/ /usr/local/jdk1.6
#编辑环境变量
[root@localhost 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@localhost local]# source /etc/profile
2.部署amoeba代理
[root@localhost local]# mkdir /usr/local/amoeba
[root@localhost opt]# tar zxf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
[root@localhost opt]# /usr/local/amoeba/bin/amoeba
amoeba start|stop ##说明安装成功
3.在三台MySQL上添加权限开放给amoeba访问
mysql> grant all on *.* to 'test'@'14.0.0.%' identified by 'abc123';
4.继续在amoeba服务器上配置,修改主配置文件
[root@localhost ~]# cd /usr/local/amoeba/conf/
[root@localhost conf]# ls
access_list.conf dbserver.dtd functionMap.xml rule.dtd
amoeba.dtd dbServers.xml log4j.dtd ruleFunctionMap.xml
amoeba.xml function.dtd log4j.xml rule.xml
#30行加入客户端访问amoeba的账户和密码
amoeba
123456
#117行去掉注释,并修改默认池、写入池、读取池的参数
master
master
slaves
5.修改dbServers.xml 文件
[root@localhost conf]# vim dbServers.xml
#26、29行去掉注释,指定为amoeba创建的允许读取数据库的用户名和密码
test
abc123
#45行开始配置三个服务器主机名和地址
14.0.0.20
14.0.0.30
14.0.0.40
#末尾指定名为slaves的poolNames中pools的主机名
...省略内容
slave1,slave2
额外需要注意!!
阿米巴做读写分离的时候:5.7版本没有test默认数据库
#23行需要注意!!!mysql5.7版本,默认没有test数据库所以修改为mysql数据库,5.5版本可忽略
mysql
[root@localhost conf]# /usr/local/amoeba/bin/amoeba start&
[root@localhost conf]# netstat -ntap | grep java
#测试用客户端(在Amoeba服务器上)
[root@localhost conf]# yum -y install mysql
[root@localhost conf]# mysql -u amoeba -p123456 -h 14.0.0.10 -P8066 #连接amoeba服务器
验证1:
在master上
[root@localhost ~]# mysql -u root -p
mysql> use school;
mysql> create table info(id int,name varchar(10));
在两台slave上
mysql> stop slave; ##关闭同步
在客户端上,插入info表一条数据
MySQL [school]> insert into info values(1,'lisi');
结果:
只有在主服务器中能看到刚才插入的记录,两台从服务器和客户端上中均无法查看到,说明数据是写入到master服务器,读的时候从slave服务器中读。
验证2:
在slave1中写入一条记录
mysql> insert into info values(2,'slave1');
在slave2中写入一条记录
mysql> insert into info values(3,'slave2');
结果:
在客户端中查询info表中的记录,会发现是轮询从两个从服务器中读的。