一般大型网站为了缓解大量的并发访问,会在web端实现负载均衡,但是这是远远不够的。到了数据存储层、数据访问层,如果还是传统的架构,或者只是依靠一台服务器,大量的数据库连接操作,会导致数据库面临崩溃的危险。进而造成数据丢失,后果不堪设想。所以我们会考虑如何减少数据库的连接,一方面进行代码的优化,采用优秀的数据缓存技术如memcached,如果资金丰厚的话,必然会想到假设服务器群,来分担主数据库的压力。今天我们就利用MySQL主从配置,实现读写分离,分散数据库的压力。这种方式,很多网站都有应用,今天只是总结学习一下。
读写分离的环境:
1.mysql集群(一般是一主多从,多主多从,本文一主多从来举例)
2.读写分离中间件(本文以amoeba举例)
3.mysql客户端程序
Amoeba实现读写分离的原理图如下
amoeba作为访问数据库的前端程序,当其接收到来自客户端或者是应用段的sql语句对数据库做处理的时候,将sql语句进行分类,比如sql语句中有select关键词则作为数据库读操作,否则作为数据库写操作。Amoeba作为数据库和客户端的中间件,会同时链接master数据库和slave数据库。由于一般网站读操作远多于写操作,所以我们定义master数据库做为写操作的数据库,slave数据库作为读操作的数据库。这样amoeba就会将来自于客户端的写操作路由到master数据库,将读操作路由到slava数据库,来实现读写分离功能。
1.mysql主从同步环境搭建
这里就不详细介绍了,网上有很多,也很简单,我们这里是一主多从的环境。
2.amoeba配置读写分离
1)amoeba需要java环境的支持,首先查看一下系统里是否安装java环境
[root@zabbix tools]#java -version java version "1.8.0_101"
Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)
我这里已经安装了java环境,所以会有上面的信息,如果没有安装的话可以到oracle官网去下载你的系统可用的java安装rpm包。
[root@zabbix tools]# wget http://download.oracle.com/otn-pub/java/jdk/8u101-b13/jdk-8u101-linux-x64.rpm[root@zabbix tools]# ls jd*jdk-8u101-linux-x64.rpm[root@zabbix tools]# rpm -ivh jdk-8u101-linux-x64.rpm添加Java环境变量:用find命令查找下Java的安装目录[root@zabbix tools]#export JAVA_HOME=/usr/Java/jdk1.8.0_101 [root@zabbix tools]#export PATH=$JAVA_HOME/bin:$PATH [root@zabbix tools]#export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
2)下载解压安装amoeba软件包
[root@zabbix tools]# wget http://101.96.10.43/jaist.dl.sourceforge.net/project/amoeba/Amoeba%20for%20mysql/3.x/amoeba-mysql-3.0.5-RC-distribution.zip [root@zabbix tools]#lsamoeba-mysql-3.0.5-RC-distribution.zip[root@zabbix tools]#mkdir -p /tmp/amoeba [root@zabbix tools]#mkdir -p /usr/local/amoeba[root@zabbix tools]#unzip -d /tmp/amoeba/ amoeba-mysql-3.0.5-RC-distribution.zip[root@zabbix tools]#cp -rf /tmp/amoeba/amoeba-mysql-3.0.5-RC/* /usr/local/amoeba/
2)配置amoeba软件
amoeba的配置文件主要在conf目录下面,其中我们要修改的主要是amoeba.xml和dbServer.xml两个配置文件
amoeba.xml修改以下几部分:
<property name="ipAddress">127.0.0.1</property> //amoeba服务监听的IP<property name="user">root</property> //amoeba的管理账号<property name="password">root</property> //amoeba的管理密码<property name="defaultPool">multiPool</property> //amoeba的默认数据库集群(最好是写操作的集群)<property name="writePool">master</property> //amoeba的读操作数据库集群<property name="readPool">slave1</property> //amoeba的写操作数据库集群
dbServer.xml修改以下部分:
<property name="port">3306</property> //真实数据库服务端口 <property name="schema">test</property> //真实数据库上存在的database,用于健康检测(每个真实数据库上都存在) <property name="user">test111</property> //真实数据库上用于amoeba连接数据库的账号 <property name="password">111111</property>//真实数据库上用于amoeba连接数据库的密码 <dbServer name="master" parent="abstractServer"> //dbServer name设置为master <factoryConfig> <!-- mysql ip --> <property name="ipAddress">192.168.1.11</property>//设置master的ip </factoryConfig> </dbServer> <dbServer name="slave1" parent="abstractServer">//dbServer name设置为slave1 <factoryConfig> <!-- mysql ip --> <property name="ipAddress">192.168.1.12</property>//设置slave1的ip </factoryConfig> </dbServer><dbServer name="multiPool" virtual="true"> //设置读库集群名为multiPool <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</property> //添加用于读操作的数据库 </poolConfig></dbServer>
注意:在真实的mysql数据库服务器上要根据上面配置的帐号密码给amoeba服务器访问mysql的权限
grant all on test.* to 'test1111'@'192.168.1.112' identified by '111111'; //192.168.1.112是amoeba服务器的地址flush privileges;
3)启动amoeba软件
[root@zabbix ~]#/usr/local/amoeba/logs/console.log 创建amoeba的日志文件[root@zabbix ~]# ./usr/local/amoeba/bin/launcher The stack size specified is too small, Specify at least 160kError: Could not create the Java Virtual Machine.
如果启动时报以上错误,请修改amoeba目录下jvm.properties文件中以下条目的Xss数值为1024K
JVM_OPTIONS="-server -Xms256m -Xmx1024m -Xss1024k -XX:PermSize=16m -XX:MaxPermSize=96m"
重启amoeba后正常,检查一下(amoeba默认端口8066)
[root@zabbix amoeba-mysql-3.0.5-RC]# ss -lntup|grep 8066tcp LISTEN 0 128 :::8066 :::* users:(("java",pid=8104,fd=66))[root@zabbix amoeba-mysql-3.0.5-RC]#
4)连接到amoeba服务器
[root@TEST01 ~]# mysql -uroot -proot -h 192.168.1.13 -P 8066Welcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 772593148Server version: 5.1.45-mysql-amoeba-proxy-3.0.4-BETA MySQL Community Server (GPL)Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql>
从server version: 5.1.45-mysql-amoeba-proxy-3.0.4-BETA可以看出,已经正常连接到amoeba服务
读写分离测试
1)终止slave1服务器的主从同步
mysql> stop slave; Query OK, 0 rows affected (0.00 sec)
2)在slave1服务器的数据库创建一个新的db
mysql> create database read_db;Query OK, 1 row affected (0.00 sec)mysql> show databases;+--------------------+| Database |+--------------------+| information_schema || mysql || performance_schema || read_db || test |+--------------------+10 rows in set (0.00 sec)mysql>
3)连接amoeba服务,查看数据库
Your MySQL connection id is 772593148Server version: 5.1.45-mysql-amoeba-proxy-3.0.4-BETA MySQL Community Server (GPL)Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> show databases;+--------------------+| Database |+--------------------+| information_schema || mysql || performance_schema || read_db || test |+--------------------+10 rows in set (0.00 sec)mysql>
可以看到read_db数据库,amoeba读操作是从slave1拿的数据
4)连接amoeba服务,创建一张表,并查看
mysql> use testDatabase changedmysql> creat table write_table(id int);ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'creat table write_table(id int)' at line 1mysql> create table write_table(id int);Query OK, 0 rows affected (0.04 sec)mysql> show tables;Empty set (0.01 sec)mysql>
发现没有刚刚创建的表,可见数据没有插入到slave1的数据库中
在master数据库查看,发现存在刚才插入的表
[root@TEST01 ~]# mysql -uroot -poldboyWelcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 2490Server version: 5.5.32-log MySQL Community Server (GPL)Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> use testDatabase changedmysql> show tables;+----------------+| Tables_in_test |+----------------+| write_table |+----------------+1 row in set (0.01 sec)mysql>
以上的测试可以发现,amoeba已经将读操作和写操作指向不同的服务器,从而实现mysql的读写分离
目前主流的数据库读写分离软件,大家 有时间可以学习学习
mysql-proxy(不适合生产环境使用)
atlas(360基于mysql-proxy开发)
amoeba(不适合生产环境使用)
tddl(淘宝开发)部分开源,配置复杂
cobar(阿里基于Amoeba开发)不支持事务
dbware(只支持mysql)
mycat(社区活跃,支持大规模使用,且开源)
本文出自 “秦仙儿” 博客,请务必保留此出处http://youdong.blog.51cto.com/3562886/1836126