文章目录
一、概述1.1 为什么要读写分离?1.2 原理1.3 目前比较常见的MySQL读写分离分为二种:
二、实验过程2.1:实验所需要的安装包2.2:实验配置阶段
三、实验过程
一、概述
1.1 为什么要读写分离?
在企业应用中,在大量的数据请求下,单台数据库将无法承担所有的读写操作配置多台数据库服务器以实现读写分离读写分离建立在主从复制的基础上
1.2 原理
读写分离就是只在主服务器上写,只在从服务器上读主数据库处理事务性查询,而从数据库处理 select 查询数据库复制被用来把事务性查询导致的变更同步到集群中的从数据库
1.3 目前比较常见的MySQL读写分离分为二种:
第一种
基于程序代码内部实现 在代码中根据select、insert进行路由分类,这类方法也是目前生产环境应用广泛的,优点是性能较好,因为在程序代码中实现,不需要增加额外的设备作为硬件开支;缺点是需要开发人员来实现,运维人员无从下手。
第二种
基于中间代理层实现 代理一般位于客户端和服务器之间,代理服务器接受到客户端的请求后通过判断后转发到后端数据库,有二个代表性程序:
MySQL-Proxy。 ----MySQL的开源项目,通过自带的lua脚本进行SQL判断,MySQL官方不建议用这个在生产环境中
Amoeba(变形虫) ----由陈思儒开发,曾就职于阿里巴巴,该程序由Java语言开发,阿里将其用于生产环境
但是它不支持事物和存储过程。
二、实验过程
2.1:实验所需要的安装包
2.2:实验配置阶段
在开始实验前,我们需要先配置三台MySQL服务器的主从复制。具体配置方法在我上一篇博客中如果是图形化界面,那就已经有了java环境,我们需要先卸载原有的java环境!
[root@localhost ~
]
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 ~
]
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 ~
]
[root@localhost ~
]
[root@localhost ~
]
[root@localhost ~
]
然后上传Jdk到opt目录
[root@localhost ~
]
[root@localhost opt
]
[root@localhost opt
]
[root@localhost opt
]
'//将如下配置文件插到最底下'
export JAVA_HOME
=/usr/local/java
export JRE_HOME
=/usr/local/java/jre
'//java环境jre java的虚拟机 简称JVM'
export PATH
=$PATH:/usr/local/java/bin
export CLASSPATH
=./:/usr/local/java/lib:/usr/local/java/jre/lib
'//类的位置'
[root@localhost opt
]
[root@localhost opt
]
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
[root@localhost opt
]
[root@localhost opt
]
[root@localhost opt
]
[root@localhost opt
]
[root@localhost opt
]
JVM_OPTIONS
="-server -Xms256m -Xmx1024m -Xss196k -XX:PermSize=16m -XX:MaxPermSize=96m"
JVM_OPTIONS
="-server -Xms1024m -Xmx1024m -Xss256k" 修改java虚拟机内存大小
= >> wq 保存
制作amoeba管理脚本
[root@localhost opt
]
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
= >> wq 保存
[root@localhost opt
]
[root@localhost opt
]
[root@localhost opt
]
ctrl + c
'//开启后 ctrl + c 停止就行了'
[root@localhost opt
]
[root@localhost opt
]
在三台mysql数据库中为amoeba授权
[root@localhost ~
]
mysql
> create database
test;
Query OK, 1 row affected
(0.01 sec
)
mysql
> GRANT ALL ON *.* TO test@
'20.0.0.%' IDENTIFIED BY
'12345';
mysql
> FLUSH PRIVILEGES
;
mysql
> quit
[root@localhost ~
]
mysql
> GRANT ALL ON *.* TO test@
'20.0.0.%' IDENTIFIED BY
'12345';
mysql
> FLUSH PRIVILEGES
;
mysql
> quit
[root@localhost ~
]
mysql
> GRANT ALL ON *.* TO test@
'20.0.0.%' IDENTIFIED BY
'12345';
mysql
> FLUSH PRIVILEGES
;
mysql
> quit
[root@localhost opt
]
[root@localhost amoeba
]
---28行-----设置客户端连接amoeba前端服务器时使用的用户名和密码----
<property name
="user">amoeba
</property
>
----30行---------
<property name
="password">123456
</property
>
------------------以上配置用于客户端连接用户名密码-------------
---83-去掉注释-同时把默认的server1改成master,把默认的servers改成 slaves
<property name
="defaultPool">master
</property
>
<property name
="writePool">master
</property
>
<property name
="readPool">slaves
</property
> '//上面修改后如下' <!-- --
> 这种注释一定要去掉
82
<property name
="LRUMapSize">1500
</property
>
83
<property name
="defaultPool">master
</property
>
84
<property name
="writePool">master
</property
>
85
<property name
="readPool">slaves
</property
>
86
<property name
="needParse">true
</property
>
[root@localhost amoeba
]
--26-29--去掉注释--
<property name
="user">test
</property
>
<property name
="password">12345
</property
>
-----------------以上是授权数据库账号和密码的---------------------
--------主服务器地址-----------
43
<dbServer name
="master" parent
="abstractServer">
46
<property name
="ipAddress">20.0.0.25
</property
>
--------从服务器地址-----------
--50--从服务器主机名1--
<dbServer name
="slave1" parent
="abstractServer">
--53--从服务器IP地址1--
<property name
="ipAddress">20.0.0.24
</property
>
<dbServer name
="slave2" parent
="abstractServer">
<factoryConfig
>
<!-- mysql ip --
>
<property name
="ipAddress">20.0.0.23
</property
>
</factoryConfig
>
</dbServer
>
----------改另一个配置------------
<dbServer name
="slaves" virtual
="true">
<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
>
</poolConfig
>
</dbServer
>
修改完配置之后,重启一下amoeba
[root@localhost amoeba
]
[root@localhost amoeba
]
tcp6 0 0 :::8066 :::* LISTEN 9058/java
tcp6 0 1 20.0.0.22:33820 20.0.0.25:3306 SYN_SENT 9058/java
三、实验过程
测试用客户端 20.0.0.27
[root@localhost ~
]
[root@localhost ~
]
[root@localhost ~
]
[root@localhost ~
]
在主mysql上创建数据库 20.0.0.25
[root@localhost ~
]
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关闭同步 20.0.0.24
[root@localhost ~
]
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关闭同步 20.0.0.23
[root@localhost ~
]
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上插入数据 20.0.0.25
[root@localhost ~
]
mysql
> use
test;
Database changed
mysql
> insert into zhang1 values
('1',
'zhang',
'this_is_master');
Query OK, 0 rows affected
(0.05 sec)
登录客户端 20.0.0.27
[root@localhost ~
]
MySQL
[(none
)]> show databases
;
+--------------------+
| Database
|
+--------------------+
| information_schema
|
| db_test
|
| mysql
|
| performance_schema
|
| sys
|
| test |
+--------------------+
6 rows
in set (0.01 sec
)
'//这时候我们查找数据,只能找到在从服务器1和从服务器2的数据。'
'//此时读写分离已经生效,从服务器负责读的功能,而我们客户端查找就相当于读的功能。'
'//上述实验,可以查看从1和从2,证明实现数据读取负载均衡'
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
)
在客户机上 20.0.0.27 继续写输数据,按照正常的规则应该是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
)
[root@localhost ~
]
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
)
[root@localhost ~
]
mysql
> use
test;
Database changed
mysql
> select * from zhang1
;
+------+-------+----------------+
| id | name
| address
|
+------+-------+----------------+
| 2
| zhang
| this_is_slave1
|
+------+-------+----------------+
1 row
in set (0.00 sec
)
[root@localhost ~
]
mysql
> use
test;
Database changed
mysql
> select * from zhang1
;
+------+-------+----------------+
| id | name
| address
|
+------+-------+----------------+
| 3
| zhang
| this_is_slave2
|
+------+-------+----------------+
1 row
in set (0.00 sec
)