MySQL 读写分离原理

*读写分离就是只在主服务器上写,只在从服务器上读
*主数据库出来事务性查询,而从数据库处理select查询
*数据库复制被用来把事务性查询导致的变更同步到集群中的从数据库

在这里插入图片描述

案例概述

在企业应用中,在大量的数据请求下,单台数据库将无法承担所有的读写操作*
*配置多台数据库服务器已实现读写分离
*本案例在主从复制的基础上实现读写分离

实验部署

注释:

  1. 需要五台虚拟机完成该实验
  2. 其中有一台是主服务器,俩台从服务器,一台amoeba服务器(该服务器的作用,把客户的读写的数据进行分离),一台客户机
  3. 最重要一点,该实验是基于已经搭建好了主从同步的服务器进行操作(这边就不在重新演示主从同步实验了,如果有小伙伴对主从同步不是太了解的话,可以看下小编上篇博客,写的就会主从同步)

实验服务器配置信息

主机操作系统IP地址主要软件
amoeba centos-7.6-X86_64, jdk-8u144-linux-x64.tar.gz192.168.100.41amoeba-mysql-3.0.5-RC-distribution.zip
Master centos-7.6-X86_64 192.168.100.42 mysql-boost-5.7.20.tar.gz
Slave1 centos-7.6-X86_64 192.168.100.43 mysql-boost-5.7.20.tar.gz
Slave2 centos-7.6-X86_64 192.168.100.44 mysql-boost-5.7.20.tar.gz
客户机 centos-7.6-X86_64 192.168.100.45 mysql-boost-5.7.20.tar.gz

实验的操作步骤


#####配置MySQL读写分离. 192.168.100.41 #####

###卸载原有的java环境###
[root@localhost ~]# java -version    ##确定java版本  1.8.0_181的 有点高
openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)

[root@localhost ~]# rpm -qa |grep java
java-1.8.0-openjdk-headless-1.8.0.181-7.b13.el7.x86_64          ####卸载
tzdata-java-2018e-3.el7.noarch
python-javapackages-3.4.1-11.el7.noarch
java-1.8.0-openjdk-1.8.0.181-7.b13.el7.x86_64                          ####卸载
javapackages-tools-3.4.1-11.el7.noarch
java-1.7.0-openjdk-1.7.0.191-2.6.15.5.el7.x86_64                      ####卸载
java-1.7.0-openjdk-headless-1.7.0.191-2.6.15.5.el7.x86_6       ####卸载

##查出openjdk相关的文件并且删除它###
[root@localhost ~]#  rpm -e --nodeps java-1.8.0-openjdk-headless-1.8.0.181-7.b13.el7.x86_64
[root@localhost ~]#  rpm -e --nodeps java-1.8.0-openjdk-1.8.0.181-7.b13.el7.x86_64
[root@localhost ~]#  rpm -e --nodeps java-1.7.0-openjdk-1.7.0.191-2.6.15.5.el7.x86_64
[root@localhost ~]#  rpm -e --nodeps java-1.7.0-openjdk-headless-1.7.0.191-2.6.15.5.el7.x86_64


##安装JDK##
上传JDK到opt目录
[root@localhost ~]# cd /opt
[root@localhost opt]# tar xzvf jdk-8u144-linux-x64.tar.gz  解压
[root@localhost opt]# mv jdk1.8.0_144/ /usr/local/java  把jdk移到到java下

[root@localhost opt]# vi /etc/profile  开始配置环境变量
export JAVA_HOME=/usr/local/java  指定java的工作目录
export JRE_HOME=/usr/local/java/jre   jre是java的虚拟机
export PATH=$PATH:/usr/local/java/bin  java的命令能让系统识别
export CLASSPATH=./:/usr/local/java/lib:/usr/local/java/jre/lib     最下面添加

[root@localhost opt]# source /etc/profile
[root@localhost opt]# java -version         ###java环境变成1.8.0_144的##
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

#####安装amoeba------https://sourceforge.net/projects/amoeba/files/#####
[root@localhost opt]# yum -y install unzip   ###如果unzip命令没有,必须装下,如果装了,此步骤跳过##

[root@localhost opt]# unzip amoeba-mysql-3.0.5-RC-distribution.zip -d /usr/local/
[root@localhost opt]# mv /usr/local/amoeba-mysql-3.0.5-RC/ /usr/local/amoeba
[root@localhost opt]# chmod -R 755 /usr/local/amoeba/

[root@localhost opt]#vi /usr/local/amoeba/jvm.properties
JVM_OPTIONS="-server -Xms256m -Xmx1024m -Xss196k -XX:PermSize=16m -XX:MaxPermSize=96m" //32行修改成如下
JVM_OPTIONS="-server -Xms1024m -Xmx1024m -Xss256k"

######制作amoeba管理脚本####
[root@localhost opt]# vi /etc/init.d/amoeba

#!/bin/bash
#chkconfig: 35 62 62
#
export JAVA_HOME=/usr/local/java
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
NAME=Amoeba
AMOEBA_BIN=/usr/local/amoeba/bin/launcher
SHUTDOWN_BIN=/usr/local/amoeba/bin/shutdown
PIDFILE=/usr/local/amoeba/Amoeba-MySQL.pid
SCRIPTNAME=/etc/init.d/amoeba

case "$1" in
start)
echo -n "Starting $NAME... "
$AMOEBA_BIN
echo " done"
;;
stop)
echo -n "Stoping $NAME... "
$SHUTDOWN_BIN
echo " done"
;;
restart)
$SHUTDOWN_BIN
sleep 1
$AMOEBA_BIN
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart}"
exit 1
;;
esac

[root@localhost opt]# chmod +x /etc/init.d/amoeba
[root@localhost opt]# chkconfig --add amoeba


service amoeba start
ctrl + c
netstat -anpt | grep 8066 //默认监听在8066端口

####在三台mysql数据库中为amoeba授权####
##登录192.168.100.42终端###
[root@localhost ~]# mysql -u root -p              ####输入密码abc123
mysql> create database test;
Query OK, 1 row affected (0.01 sec)
mysql> GRANT ALL  ON *.* TO test@'20.0.0.%' IDENTIFIED BY 'abc123';
mysql> FLUSH PRIVILEGES;
mysql> quit

##登录192.168.100.43终端###
[root@localhost ~]# mysql -u root -p              ####输入密码abc123
mysql> GRANT ALL  ON *.* TO test@'20.0.0.%' IDENTIFIED BY 'abc123';
mysql> FLUSH PRIVILEGES;
mysql> quit

##登录192.168.100.44终端###
[root@localhost ~]# mysql -u root -p              ####输入密码abc123
mysql> GRANT ALL  ON *.* TO test@'20.0.0.%' IDENTIFIED BY 'abc123';
mysql> FLUSH PRIVILEGES;
mysql> quit

#######在前端服务器上 192.168.100.41 你可以把它理解成调度器 ######




[root@localhost opt]# cd /usr/local/amoeba
[root@localhost amoeba]# vi conf/amoeba.xml                                                该配置文件是针对客户机连amoeba调速器的配置文件
---28行-----设置客户端连接amoeba前端服务器时使用的用户名和密码----
 <property name="user">amoeba</property>                   //amoeba 指的是去连接amoeba调速器的账号
----30行---------
 <property name="password">123456</property>            //amoeba 指的是去连接amoeba调速器的密码
------------------------------------以上配置用于客户端连接用户名密码-------------

---83-去掉注释-同时把默认的server1改成master,把默认的servers改成 slaves
 <property name="defaultPool">master</property>             //默认的池是名称叫master
 <property name="writePool">master</property>               //默认写的池是主服务器
 <property name="readPool">slaves</property>                 //默认读的池是从服务器

在这里插入图片描述
修改后的样子

在这里插入图片描述

[root@localhost amoeba]# vi conf/dbServers.xml
在这里插入图片描述



//该配置文件是针对amoeba.xml去连接数据库的
--26-29--去掉注释--
 <property name="user">test</property>                          //amoeba.xml去连接数据库的使用的账号
   
 <property name="password">abc123</property>      //amoeba.xml去连接数据库的使用的密码

------主服务器地址---
 43 <dbServer name="master"  parent="abstractServer">
 46 <property name="ipAddress">192.168.100.42</property>

--50-从服务器主机名-
<dbServer name="slave1"  parent="abstractServer">
--53-从服务器地址-
 <property name="ipAddress">192.168.100.43</property>



<!-- mysql schema -->
<property name="schema">test</property>  #####数据库中要有此处定义的数据库,否则客户端连接后会报错,默认我用test数据库,创建是test数据库不要弄错了

        <dbServer name="master"  parent="abstractServer">        #####name后面改成 master
                <factoryConfig>
                        <!-- mysql ip -->
                        <property name="ipAddress">192.168.100.42</property>    ####ipAddress加上主mysql的IP地址
                </factoryConfig>
        </dbServer>

        <dbServer name="slave1"  parent="abstractServer">        #####name后面改成 slave1
                <factoryConfig>
                        <!-- mysql ip -->
                        <property name="ipAddress">192.168.100.43</property>    ###ipAddress加上从1mysql的IP地址
                </factoryConfig>
        </dbServer>
###注意啦!在脚本中slave2是没有的,需要复制下#####
        <dbServer name="slave2"  parent="abstractServer">        #####name后面改成 slave2
                 <factoryConfig>
                        <!-- mysql ip -->
                        <property name="ipAddress">192.168.100.44</property>   ###ipAddress加上从2mysql的IP地址
                 </factoryConfig>
        </dbServer>
        
        <dbServer name="slaves" virtual="true">                 #####name后面改成 slaves
                <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
                        <!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
                        <property name="loadbalance">1</property>

                        <!-- Separated by commas,such as: server1,server2,server1 -->
                        <property name="poolNames">slave1,slave2</property>            #####poolNames后面改成 slave1,slave2
                </poolConfig>
        </dbServer> 
 
 

上述写的配置文件比较多,但是看到的小伙伴也不要害怕,大部分都是文件自带的配置,小编只是在配置文件中进行了增,删,改,查,也可以看下图一和图二修改后的样子

在这里插入图片描述
图一

在这里插入图片描述
图二

[root@localhost amoeba]# service amoeba restart
[root@localhost amoeba]# netstat -anpt | grep java

#######测试用客户端 192.168.100.45#######

service firewalld stop
setenforce 0

yum install -y mysql
mysql -u amoeba -p123456 -h 192.168.100.41 -P8066   ##### 登录192.168.100.45 amoeba服务端

###在主mysql上创建数据库 192.168.100.42  ###
[root@localhost ~]# mysql -u root -p          ###输入mysql密码 abc123
mysql> use test;
Database changed
mysql> create table zhang1 (id int(10),name varchar(10),address varchar(20));
Query OK, 0 rows affected (0.05 sec)

###在从1 mysql关闭同步 192.168.100.43###
[root@localhost ~]# mysql -u root -p          ###输入mysql密码 abc123
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
mysql> use test;
Database changed
mysql> insert into zhang1 values('2','zhang','this_is_slave1');
Query OK, 1 row affected (0.00 sec)
###在从2 mysql关闭同步 192.168.32.13###
[root@localhost ~]# mysql -u root -p          ###输入mysql密码 abc123
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
mysql> use test;
Database changed
mysql> insert into zhang1 values('3','zhang','this_is_slave2');
Query OK, 1 row affected (0.00 sec)

###在主mysql上插入数据 192.168.100.42  ###
[root@localhost ~]# mysql -u root -p          ###输入mysql密码 abc123
mysql> use test;
Database changed
mysql> insert into zhang1 values('1','zhang','this_is_master');
Query OK, 0 rows affected (0.05 sec)

######登录客户端  192.168.100.45#####
[root@localhost ~]# mysql -u amoeba -p123456 -h 192.168.32.14 -P8066
MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| bdqn               |
| db_test            |
| mysql              |
| performance_schema |
| sys                |
| test               |                       #####发现数据库test
+--------------------+
7 rows in set (0.01 sec)

MySQL [(none)]> use test;                    ####进入数据库test
Database changed
MySQL [test]> select * from zhang1;           ###查看zhang信息 发现进入slave1 数据中的数据
| id   | name  | address        |
+------+-------+----------------+
|    2 | zhang | this_is_slave1 |
+------+-------+----------------+
1 row in set (0.00 sec)

MySQL [test]> select * from zhang;          ###查看zhang信息 发现进入slave2 数据中的数据
+------+-------+----------------+
| id   | name  | address        |
+------+-------+----------------+
|    3 | zhang | this_is_slave2 |
+------+-------+----------------+
1 row in set (0.01 sec)

#########上述实验,实现数据读取负载均衡#######
###在客户机上 192.168.100.45  继续写输数据,按照正常的规则应该是slave1 和slave2是看不见的
MySQL [(none)]> use test;
Database changed
MySQL [test]> insert into zhang1 values('4','zhang','write_test');
Query OK, 1 row affected (0.01 sec)

######登录mastar 192.168.100.42 ###
[root@localhost ~]# mysql -u root -p        
mysql> use test; 
Database changed
mysql> select * from zhang1;
+------+-------+----------------+
| id   | name  | address        |
+------+-------+----------------+
|    1 | zhang | this_is_master |
|    4 | zhang | write_test     |
+------+-------+----------------+
2 rows in set (0.00 sec)
######登录slave1 192.168.100.43###
[root@localhost ~]# mysql -u root -p 
mysql> use test; 
Database changed
mysql> select * from zhang1; 
+------+-------+----------------+
| id   | name  | address        |
+------+-------+----------------+
|    2 | zhang | this_is_slave1 |
+------+-------+----------------+
1 row in set (0.00 sec)
######登录slave2 192.168.100.44 ###
[root@localhost ~]# mysql -u root -p 
mysql> use test; 
Database changed
mysql> select * from zhang1; 
+------+-------+----------------+
| id   | name  | address        |
+------+-------+----------------+
|    3 | zhang | this_is_slave2 |
+------+-------+----------------+
1 row in set (0.00 sec)

#######上述验证结果如下###
在客户端(192.168.100.45)上操作写入数据,数据是往master上写的,在salve1和slave2上看不到写的数据

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐