文章目录
前言
- 生产环境中,服务器不可能只有一台,而多台服务器的存在必然要用到主从复制同步。
一:MySQL主从复制
1.1:原因
- 在企业网站中,后端MySQL数据库只有一台时,会有以下问题:
- 遇到单点故障,服务不可用
- 无法处理大量的高并发数据请求
- 数据丢失将会造成很大损失
1.2:解决办法
- 增加MySQL数据库服务器,对数据进行备份,形成主备
- 确保主备MySQL数据库服务器数据是一样的
- 主服务器宕机了,备份服务器继续工作,数据有保障
- MySQL主从复制与读写分离是密切相关的
1.3:更高级的解决方案
-
通过主从复制的方式来同步数据,再通过读写分离来提升数据库的并发负载能力
-
Amoeba:是一个以MySQL为底层数据存储,并对应用提供MySQL协议接口的proxy,外号变形虫
读取请求发送给从服务器时,采用轮询调度算法
-
主服务器挂掉,我们会采用MHA解决(此实验用不到)
-
此实验涉及到的账号权限
- 主从同步账号
- 节点服务器开放调度账号
- Amoeba代理账号
1.4:MySQL主从复制的类型
- 基于语句的复制(默认)
- 在主服务器上执行的语句,从服务器执行同样的语句
- 基于行的复制
- 把改变的内容复制到从服务器
- 混合类型的复制
- 一旦发现基于语句无法精确复制时,就会采用基于行的复制
1.5:主从复制的工作过程
-
Master
启用binlog日志 -
Slave
Slave_IO:复制master主机 binlog日志文件里的SQL命令到本机的relay-log文件里。
Slave_sQL:执行本机relay-log文件里的SQL语句,实现与Master数据一致。
-
-
slave端的IO线程连上master端,请求
-
master端返回给slave端,bin log文件名和位置信息
-
IO线程把master端的bin log内容依次写到slave端relay log里,并把master端的bin-log文件名和位置记录到master.info里。
-
salve端的sql线程,检测到relay log中内容更新,就会解析relay log里更新的内容,并执行这些操作
-
二:MySQL读写分离原理
2.1:原理
- 读写分离就是只在主服务器上写,只在从服务器上读
- 主数据库处理事务性査询,而从数据库处理 select査询
- 数据库复制被用来把事务性査询导致的变更同步到集群中的从数据库
- 由MySQL代理面向客户端提供服务
- 收到SQL写请求时,交给master服务器处理
- 收到SQL读请求时,交给slave服务器处理
2.2:为什么会形成读写分离?
- 在企业应用中,在大量的数据请求下,单台数据库将无法承担所有的读写操作
- 配置多台数据库服务器以实现读写分离
- 读写分离建立在主从复制的基础上
2.3: 读写分离的基础:主从复制
三: 主从复制实验
3.1:环境
- VMware软件
- 环境依赖上一篇博客做的主从复制的结果
- 一台centos7服务器当做client
- 一台centos7服务器作为Amoeba服务器
- 三台centos7服务器作为mysql数据库服务器,一主二从
- 3台MySQL服务器时间必须一致,才可实现主从复制
master:192.168.100.150
slave01::192.168.100.160
slave02:192.168.100.170
amoeba: 192.168.100.130
client: 192.168.100.120
3.3:实验目的
- 通过向mysql主服务器和从服务器写东西,验证:
- 客户机通过amoeba服务器写入是写入mysql主服务器
- 客户机通过amoeba服务器读取数据是从两个slave从服务器上轮询读取数据的
3.4:实验过程
3.4.1:防火墙设置
- 和主从同步一样,确定都关闭
systemctl stop firewalld.service
setenforce 0
3.4.2:搭建mysql主从复制环境
- 主从三台MYSQL服务器编译安装MySQL
3.4.3: 主服务器master配置
-
[root@master ~]# vim /etc/my.cnf server-id = 11 '主服务器id' log-bin=master-bin '设置二进制日志名' log-slave-updates=true '从服务器更新二进制日志' [root@master ~]# systemctl restart mysqld.service [root@master ~]# mysql -uroot -p mysql> grant replication slave on *.* to 'myslave'@'192.168.100.%‘ identified by '123456'; '192.168.100.网段的从服务器拥有复制权限,可以使用myslave身份123456密码复制所有的库和表' mysql> flush privileges; '刷新' mysql> show master status; '查看当前位置id,非常重要,之后不得有更改数据库操作' +-------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +-------------------+----------+--------------+------------------+-------------------+ | master-bin.000001 | 604 | | | | +-------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec)
3.4.4 从服务器配置
-
两台从服务器除了server-id不一样,其它配置都一样
-
[root@slave02 ~]# vim /etc/my.cnf server-id = 33 '主从服务器id不能一样,另一台从服务器为22' relay-log=relay-log-bin '设置二进制日志名' relay-log-index=slave-relay-bin.index '从服务器更新二进制日志' [root@slave02 ~]# systemctl start mysqld [root@slave02 mysql]# mysql -uroot -p mysql> change master to master_host='192.168.100.150',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=604; '在从服务器中添加主服务器,登录用户,密码,日志文件,位置id''这里一定要和上文主从授权的账号密码一致' mysql> start slave; '开启主从同步' mysql> show slave status\G; '查看主从同步情况' ...... Slave_IO_Running: Yes 'IO运行正常' Slave_SQL_Running: Yes 'SQL运行正常' 'slave01按照同样方法修改,注意端口号不要相同'
-
此时主从复制已全部配置完毕,进行验证
-
'主服务器创建库和表' mysql> create database accp; Query OK, 1 row affected (0.00 sec) mysql> use accp; Database changed mysql> create table mytable(id int(4),name varchar(50)); Query OK, 0 rows affected (0.01 sec)
'两台从服务器均同步成功' mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | accp | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) mysql> use accp; Database changed mysql> show tables; +----------------------+ | Tables_in_mydatabase | +----------------------+ | mytable | +----------------------+ 1 row in set (0.00 sec)
四: 读写分离实验
4.1: 搭建amoeba服务
-
'三台mysql服务器添加权限和用户开放给amoeba访问' mysql> grant all on *.* to test@'192.168.100.%' identified by '123.com'; mysql> flush privileges;
-
//上传jdk-6u14-linux-x64.bin amoeba-mysql-binary-2.2.0.tar.gz 到/opt [root@amoeba opt]# cp jdk-6u14-linux-x64.bin /usr/local/ [root@amoeba opt]# cd /usr/local/ [root@amoeba local]# chmod +x jdk-6u14-linux-x64.bin [root@amoeba local]# ./jdk-6u14-linux-x64.bin '执行jdk程序,一直空格' Do you agree to the above license terms? [yes or no] yes '这里输入yes等待安装成功即可' [root@amoeba local]# mv jdk1.6.0_14/ jdk1.6 [root@amoeba 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@amoeba local]# source /etc/profile [root@amoeba local]# mkdir /usr/local/amoeba [root@amoeba local]# cd /opt [root@amoeba opt]# tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/ [root@amoeba opt]# chmod -R 755 /usr/local/amoeba/ [root@amoeba opt]# /usr/local/amoeba/bin/amoeba '查看是否安装成功' amoeba start|stop '安装成功' [root@amoeba opt]# cd /usr/local/amoeba/conf [root@amoeba conf]# vim amoeba.xml '配置文件中需要修改的行' '此段设置的是客户端通过amoeba用户和123456密码访问amoeba服务器' //第30行修改 30 <property name="user">amoeba</property> //客户访问amoeba账户 31 32 <property name="password">123456</property> //使用123456密码访问amoeba服务器' //第115行修改 //开启读写功能池设定' 115 <property name="defaultPool">master</property> //修改默认地址池为master 116 117 <!-- --> '//117行取消注释' 118 <property name="writePool">master</property> //修改写为master 119 <property name="readPool">slaves</property> //修改读为slaves 120 //120行删除-->注释符号 [root@amoeba conf]# vim dbServers.xml '编辑数据库配置文件' 22 <!-- mysql schema --> 23 <property name="schema">mysql</property> '//amoeba默认读取的库将test修改为mysql;23行test修改为mysql' 5.5版本这里是test,原本有这个库,5.7没有自带这个test库,所以要修改,不修改报错 24 //'设置amoeba访问mysql数据库的用户和密码',这里要与上一个三个mysql代码块授权账号密码一致 25 <!-- mysql user --> 26 <property name="user">test</property> '//26行修改用户名test' 27 28 <!-- mysql password --> '//28行-30行取消注释' 29 <property name="password">123.com</property> '//29行修改密码123.com' 45 <dbServer name="master" parent="abstractServer"> '//45行主mysql服务器名称修改为master' 46 <factoryConfig> 47 <!-- mysql ip --> 48 <property name="ipAddress">192.168.100.150</property> '48行//修改主服务器IP' 49 </factoryConfig> 50 </dbServer> 51 52 <dbServer name="slave1" parent="abstractServer"> '//52行修改从服务器1的名称' 53 <factoryConfig> 54 <!-- mysql ip --> 55 <property name="ipAddress">192.168.100.160</property> '//修改从服务器1的地址' 56 </factoryConfig> 57 </dbServer> 58 '将上面从服务器配置的7行复制下来修改名称slave2和ip地址' 59 <dbServer name="slave2" parent="abstractServer"> '//修改从服务器2的名称' 60 <factoryConfig> 61 <!-- mysql ip --> 62 <property name="ipAddress">192.168.100.170</property> '//修改从服务器1的地址 63 </factoryConfig> 64 </dbServer> 65 '//修改数据库从服务器池' 66 <dbServer name="slaves" virtual="true"> //修改服务器的名称为slaves' 67 <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool"> 68 <!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA--> 69 <property name="loadbalance">1</property> 70 71 <!-- Separated by commas,such as: server1,server2,server1 --> 72 <property name="poolNames">slave1,slave2</property> '//添加两个从服务器名称slave1,slave2' 73 </poolConfig> 74 </dbServer> [root@amoeba conf]# /usr/local/amoeba/bin/amoeba start & '启动amoeba服务' [1] 10675 [root@amoeba conf]# log4j:WARN log4j config load completed from file:/usr/local/amoeba/conf/log4j.xml 2020-08-27 00:33:50,480 INFO context.MysqlRuntimeContext - Amoeba for Mysql current versoin=5.1.45-mysql-amoeba-proxy-2.2.0 log4j:WARN ip access config load completed from file:/usr/local/amoeba/conf/access_list.conf 2020-08-27 00:33:50,626 INFO net.ServerableConnectionManager - Amoeba for Mysql listening on 0.0.0.0/0.0.0.0:8066. 2020-08-27 00:33:50,627 INFO net.ServerableConnectionManager - Amoeba Monitor Server listening on /127.0.0.1:15974. [root@amoeba ~]# netstat -ntap | grep 8066 tcp6 0 0 :::8066 :::* LISTEN 11060/java //8066端口一定要开启
4.2: 客户端登陆测试
-
取一台客户机Centos 7.5
-
systemctl stop firewalld.service setenforce 0 yum install mysql -y mysql -u amoeba -pabc123 -h 192.168.100.130 -P8066 MySQL [(none)]> show databases;
-
验证写入是在主服务器
mysql> create accp; mysql> use accp; mysql> create table test(id int(4),name varchar(50),info varchar(50)); '在客户端创建测试用的表格' mysql> show tables; +----------------+ | Tables_in_accp | +----------------+ | test | +----------------+ 1 row in set (0.00 sec) -------从服务器slave1和slave2停止同步 mysql> stop slave; '停止同步' Query OK, 0 rows affected (0.00 sec) -------客户端 MySQL [none]> use accp; mysql> insert into test values(1,'zhangsan','this is master'); '向表格中添加数据' Query OK, 1 row affected (0.00 sec) -------主服务器 mysql> select * from test; '查看数据正常' +------+----------+----------------+ | id | name | info | +------+----------+----------------+ | 1 | zhangsan | this is master | +------+----------+----------------+ 1 row in set (0.00 sec) -------从服务器 mysql> select * from test; '无法查看到数据' Empty set (0.00 sec)
-
验证读取的是slave服务器数据
----------slave01服务器 mysql> insert into test values(2,'lisi','this is slave1'); '添加数据' Query OK, 1 row affected (0.00 sec) ----------slave02服务器 mysql> insert into test values(3,'wangwu','this is slave2'); '添加数据' Query OK, 1 row affected (0.00 sec) ----------客户端测试 mysql> select * from test; '此时查看表格数据只能查看到客户端添加的数据,并且读取是轮询制的,读取的是从服务器的数据,读取不到 1,'zhangsan','this is master'这条数据 +------+--------+----------------+ | id | name | info | +------+--------+----------------+ | 3 | wangwu | this is slave2 | +------+--------+----------------+ 1 row in set (0.01 sec) mysql> select * from test; +------+------+----------------+ | id | name | info | +------+------+----------------+ | 2 | lisi | this is slave1 | +------+------+----------------+ 1 row in set (0.02 sec) mysql> select * from test; +------+--------+----------------+ | id | name | info | +------+--------+----------------+ | 3 | wangwu | this is slave2 | +------+--------+----------------+ 1 row in set (0.01 sec) mysql> select * from test; +------+------+----------------+ | id | name | info | +------+------+----------------+ | 2 | lisi | this is slave1 | +------+------+----------------+ 1 row in set (0.00 sec)