MYSQL分布式中间件课题研究模板.docx
《MYSQL分布式中间件课题研究模板.docx》由会员分享,可在线阅读,更多相关《MYSQL分布式中间件课题研究模板.docx(19页珍藏版)》请在冰豆网上搜索。
MYSQL分布式中间件课题研究模板
MYSQL分布式中间件
一、MYSQL数据库主从复制的实现
MySQL的主从复制是通过binlog日志来实现的,主从复制中的“主”指的是MySQL主服务器上的数据库,“从”指的是MySQL从服务器上的数据库,且这种复制是基于数据库级别的,为此从服务器中的数据库名称必须和主服务器中的数据库名称保持一致,那么,要想实现主从复制,我们至少要有两个MySQL服务器(最好是两个MySQL服务器分别位于不同的主机上,或者在一个主机上安装两个MySQL,端口不同即可)
数据库服务器的参数:
∙主服务器(master):
IP为127.0.0.1,端口为33306
∙从服务器(slave):
IP为127.0.0.1,端口为33307
∙从服务器(slave):
IP为127.0.0.1,端口为33308
主服务器配置:
修改主服务器的数据库配置文件(\mysql\bin\my.ini),在[mysqld]标签的最下面,添加如下代码:
#需要备份的数据库
binlog-do-db=mycat
#不需要备份的数据库
binlog-ignore-db=mysql
#开启二进制日志
log-bin=mysql-bin
#服务器id
server-id=1
保存退出,重启MySQL主服务器。
binlog-do-db用于指定需要同步的数据库,binlog-ignore-db指定不需要同步的数据库,如果这两个参数都不设置,则从服务器会复制主服务器的所有数据库。
一般不用root账号作同步账号,为此,我们需要在主服务器上创建一个新的用户(如user01,密码为123456)
这里我们用命令行的方式创建,方法如下:
打开cmd,切换至\mysql\bin,用root账户连接MySQL主服务器:
mysql-uroot--P33306
创建新用户:
createuser'user01'@'127.0.0.1'identifiedby'123456';
(@后面的ip地址为允许连接的客户端的ip地址。
)
然后,给新用户配置主从复制的权限:
grantreplicationslaveon*.*to'user01'@'127.0.0.1'identifiedby'123456';
(@后面的ip地址为允许连接的客户端的ip地址,如果改为'%',就表示客户端没有ip地址的限制)
如果主服务器的数据库(mycat)中,已经有数据,我们需要先手动把主服务器中的数据复制到从服务器。
方法如下:
在本案例中,我们只备份一个数据库(mycat),mycat中有一个表user,表中也已经有了数据。
为了防止我们复制数据的时候,数据库mycat中的数据发生更新,我们需要先锁定数据库,命令如下:
flushtableswithreadlock;
这个命令是全局读锁定,它会给主服务器中的所有数据库都加上读锁,这里顺便说一下读锁和写锁的区别:
∙readlock(读锁):
也叫共享锁,允许所有的读操作,但阻塞写操作,即所有连接只可以读数据,但不允许写数据。
∙writelock(写锁):
也叫排它锁、独占锁,只允许当前连接的读和写,不允许其他并发的读操作和写操作。
锁定主服务器的数据库后,我们在从服务器中,也创建一个数据库test,并将所有的表(包括表结构和表数据)都导入。
然后,我们执行下面的命令,解锁:
unlocktables;
查看主服务器的master状态:
mysql>showmasterstatus;
从服务器配置:
修改从服务器的数据库配置文件(\mysql\my.ini),在[mysqld]标签的最下面,添加如下代码:
#端口
port=33307
#服务器id
server_id=2
#开启二进制日志(从服务器不是必须要开启二进制日志)
log-bin=mysql-bin
保存退出,重启MySQL服务。
连接MySQL从服务器:
mysql-uroot--P33307
配置复制的参数:
changemastertomaster_host='127.0.0.1',master_user='user01',master_password='123456',master_port=33306,master_log_file='mysql-bin.000008',master_log_pos=498;
参数详解:
master_host:
主服务器的IP
master_user:
主服务器上新创建的用户名
master_password:
用户的密码
master_port:
主服务器的端口,如果未曾修改,默认即可。
master_log_file:
主服务器二进制日志文件的名称,填写查看主服务器的master状态时显示的File的值
master_log_pos:
日志的位置,填写查看主服务器的master状态时显示的Position的值
启动从服务器的slave复制功能:
startslave;
查看从服务器的slave状态:
mysql>showslavestatus\G
如果Slave_IO_Running和Slave_SQL_Running的值都为Yes,则说明主从复制的所有配置已成功,即从服务器已经可以自动与主服务器的数据库数据实现同步了
二、MYSQL数据库读写分离
1.数据库中间件选型:
Cobar:
阿里巴巴B2B开发的关系型分布式系统,管理将近3000个MySQL实例。
在阿里经受住了考验,后面由于作者的走开的原因cobar没有人维护了,阿里也开发了tddl替代cobar。
MyCAT:
社区爱好者在阿里cobar基础上进行二次开发,解决了cobar当时存在的一些问题,并且加入了许多新的功能在其中。
目前MyCAT社区活跃度很高,目前已经有一些公司在使用MyCAT。
总体来说支持度比较高,也会一直维护下去,
OneProxy:
数据库界大牛,前支付宝数据库团队领导楼总开发,基于mysql官方的proxy思想利用c进行开发的,OneProxy是一款商业收费的中间件,楼总舍去了一些功能点,专注在性能和稳定性上。
有朋友测试过说在高并发下很稳定。
Vitess:
这个中间件是Youtube生产在使用的,但是架构很复杂。
与以往中间件不同,使用Vitess应用改动比较大,要使用他提供语言的API接口,我们可以借鉴他其中的一些设计思想。
Kingshard:
Kingshard是前360Atlas中间件开发团队的陈菲利用业务时间用go语言开发的,目前参与开发的人员有3个左右,目前来看还不是成熟可以使用的产品,需要在不断完善。
Atlas:
360团队基于mysqlproxy把lua用C改写。
原有版本是支持分表,目前已经放出了分库分表版本。
在网上看到一些朋友经常说在高并发下会经常挂掉,如果大家要使用需要提前做好测试。
MaxScale与MySQLRoute:
这两个中间件都算是官方的吧,MaxScale是mariadb(MySQL原作者维护的一个版本)研发的,目前版本不支持分库分表。
2.MYCAT概述
2.1什么是MyCat?
简单的说,MyCAT就是:
∙一个新颖的数据库中间件产品;
∙一个彻底开源的、面向企业应用开发的“大数据库集群”;
∙支持事务、ACID、可以替代MySQL的加强版数据库;
∙一个可以视为“MySQL”集群的企业级数据库,用来替代昂贵的Oracle集群;
∙一个融合内存缓存技术、Nosql技术、HDFS大数据的新型SQLServer;
∙结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品。
2.2MyCat的目标
MyCAT的目标是:
低成本的将现有的单机数据库和应用平滑迁移到“云”端,解决数据存储和业务规模迅速增长情况下的数据瓶颈问题。
2.3MyCat的关键特性
·支持SQL92标准
支持Mysql集群,可以作为Proxy使用
支持JDBC连接ORACLE、DB2、SQLServer,将其模拟为MySQLServer使用
支持NoSQL数据库
支持galeraformysql集群,percona-cluster或者mariadbcluster,提供高可用性数据分片集群
自动故障切换,高可用性
支持读写分离,支持Mysql双主多从,以及一主多从的模式
支持全局表,数据自动分片到多个节点,用于高效表关联查询
支持独有的基于E-R关系的分片策略,实现了高效的表关联查询
支持一致性Hash分片,有效解决分片扩容难题
多平台支持,部署和实施简单
支持Catelet开发,类似数据库存储过程,用于跨分片复杂SQL的人工智能编码实现,143行Demo完成跨分片的两个表的JION查询。
支持NIO与AIO两种网络通信机制,Windows下建议AIO,Linux下目前建议NIO
支持Mysql存储过程调用
以插件方式支持SQL拦截和改写
支持自增长主键、支持Oracle的Sequence机制
2.4MyCat的优势
·基于阿里开源的Cobar产品而研发,Cobar的稳定性、可靠性、优秀的架构和性能,以及众多成熟的使用案例使得MyCAT一开始就拥有一个很好的起点,站在巨人的肩膀上,能看到更远。
·广泛吸取业界优秀的开源项目和创新思路,将其融入到MyCAT的基因中,使得MyCAT在很多方面都领先于目前其他一些同类的开源项目,甚至超越某些商业产品。
·MyCAT背后有一只强大的技术团队,其参与者都是5年以上资深软件工程师、架构师、DBA等,优秀的技术团队保证了MyCAT的产品质量。
·MyCAT并不依托于任何一个商业公司,因此不像某些开源项目,将一些重要的特性封闭在其商业产品中,使得开源项目成了一个摆设。
3.MYCAT下载和安装
3.1MyCAT使用Java开发,因为用到了JDK7的部分功能,所以在使用前请确保安装了JDK7.0,要求是JDK7.0以上,并设置了正确的Java环境变量。
目前下载的版本Mycat-server-1.6-RELEASE-20161028204710-win.tar.gz是免安装,解压在任意磁盘、根目录下,避免路径中出现中文,需配置环境变量MYCAT_HOME。
解压后的目录结构如下图所示:
目录说明:
Bin:
存放window版本和linux版本,除了提供封装成服务的版本之外,也提供nowrap的shell脚本命令,方便大家选择和修改。
Windows下运行:
mycat.batconsole在控制台启动程序,也可以装载成服务,若此程序运行有问题,也可以运行startup_nowrap.bat,确保java命令可以在命令执行。
ØConf:
存放配置文件:
lserver.xml:
是Mycat服务器参数调整和用户授权的配置文件。
lschema.xml:
是逻辑库定义和表以及分片定义的配置文件。
lrule.xml:
是分片规则的配置文件,分片规则的具体一些参数信息单独存放为文件,也在这个目录下,配置文件修改,需要重启MyCAT或者通过9066端口reload。
lwrapper.conf:
JVM配置参数等设置。
llog4j.xml:
日志存放在logs/mycat.log中,每天一个文件,日志的配置是在conf/log4j.xml中,根据自己的需要,可以调整输出级别为debug,debug级别下,会输出更多的信息,方便排查问题。
ØLib:
MyCAT自身的jar包或依赖的jar包的存放目录。
ØLogs:
MyCAT日志的存放目录。
日志存放在logs/mycat.log中,每天一个文件。
ØVersion.txt:
版本说明
3.2MyCAT启动和停止
安装服务:
mycatinstall
启动服务:
mycatstart
停止服务:
mycatstop
注意:
当修改配置文件后,需要重启mycat服务
3.3读写分离配置
3.3.1配置连接信息
Mycat的server.xml配置逻辑库的名称访问的账号密码
mycat
配置说明:
配置中name是应用连接中间件逻辑库的用户名。
mycat中password是应用连接中间件逻辑库的密码。
schemas中可以配置一个或多个。
readOnly是应用连接中间件逻辑库所具有的权限。
true为只读,false为读写都有,默认为false。
3.3.2配置数据库信息
selectuser()
33306"user="root"password="">
33307"user="root"password=""/>
33308"user="root"password=""/>
配置说明:
name属性唯一标识dataHost标签,供上层的标签使用。
maxCon属性指定每个读写实例连接池的最大连接。
也就是说,标签内嵌套的
writeHost、readHost标签都会使用这个属性的值来实例化出连接池的最大连接数。
minCon属性指定每个读写实例连接池的最小连接,初始化连接池的大小。
balance属性负载均衡类型,目前的取值有3种:
1.balance="0",不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。
2.balance="1",全部的readHost与standbywriteHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与M2互为主备),
正常情况下,M2,S1,S2都参与select语句的负载均衡。
3.balance="2",所有读操作都随机的在writeHost、readhost上分发。
4.balance="3",所有读请求随机的分发到wiriterHost对应的readhost执行,
writerHost不负担读压力,注意balance=3只在1.4及其以后版本有,1.3没有。
writeType属性负载均衡类型,目前的取值有3种:
1.writeType="0",所有写操作发送到配置的第一个writeHost,第一个挂了切到还生存的第二个writeHost,重新启动后已切换后的为准,切换记录在配置文件中:
dnindex.properties.
2.writeType="1",所有写操作都随机的发送到配置的writeHost,1.5以后废弃不推荐。
3.writeType="2",不执行写操作
switchType属性
-1表示不自动切换
1默认值,自动切换
2基于MySQL主从同步的状态决定是否切换
3基于MySQLgalarycluster的切换机制(适合集群)(1.4.1)
心跳语句为showstatuslike‘wsrep%’
dbType属性
指定后端连接的数据库类型,目前支持二进制的mysql协议,还有其他使用
JDBC连接的数据库。
例如:
mongodb、oracle、spark等。
dbDriver属性指定连接后端数据库使用的
Driver,目前可选的值有native和JDBC。
使用native的话,因为这个值执行的是二进制的mysql协议,所以可以使用mysql和maridb。
其他类型的数据库则需要使用JDBC驱动来支持。
从1.6版本开始支持postgresql的native原始协议。
如果使用JDBC的话需要将符合JDBC4标准的驱动JAR包放到MYCAT\lib目录下,并检查驱动JAR包中包括如下目录结构的文件:
META-INF\services\java.sql.Driver。
在这个文件内写上具体的Driver类名,例如:
com.mysql.jdbc.Driver。
heartbeat标签这个标签内指明用于和后端数据库进行心跳检查的语句。
例如,MYSQL可以使用selectuser(),Oracle可以使用select1fromdual等。
这个标签还有一个
connectionInitSql属性,主要是当使用Oracla数据库时,需要执行的初始化SQL
语句就这个放到这里面来。
例如:
altersessionsetnls_date_format='yyyy-mm-ddhh24:
mi:
ss'
1.4主从切换的语句必须是:
showslavestatus
writeHost标签、readHost标签
这两个标签都指定后端数据库的相关配置给mycat,用于实例化后端连接池。
唯一不同的是,writeHost指定写实例、readHost指定读实例,组着这些读写实例来满足系统的要求。
在一个dataHost内可以定义多个writeHost和readHost。
但是,如果writeHost
指定的后端数据库宕机,那么这个writeHost绑定的所有readHost都将不可用。
另一方面,由于这个writeHost宕机系统会自动的检测到,并切换到备用的writeHost上去。
3.4启动mycat
在mycat的lib包下面丢入mysql的驱动包,然后在mycat\bin目录下找到startup_nowrap.bat双击运行。
双击没有一闪而退,就启动成功了。
如果启动不成功,仔细检查配置信息
3.5测试所需jar包
4.测试代码
4.1读测试
packagetest;
importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
importjava.sql.SQLException;
importjava.sql.Statement;
publicclassMysqlConTest{
privatestaticStringurl="jdbc:
mysql:
//127.0.0.1:
8066/mycat?
useUnicode=true&characterEncoding=utf-8";
privatestaticStringusername="root";
privatestaticStringpassword="";
privatestaticStringdriverName="com.mysql.jdbc.Driver";
publicMysqlConTest(){
super();
//TODOAuto-generatedconstructorstub
}
static{
try{
Class.forName(driverName);
}catch(ClassNotFoundExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
publicstaticConnectiongetConnection()throwsSQLException{
returnDriverManager.getConnection(url,username,password);
}
publicstaticvoidclose(ResultSetrs,Statementst,Connectionconn){
try{
if(rs!
=null){
rs.close();
}
}catch(SQLExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}finally{
try{
if(st!
=null){
st.close();
}
}catch(SQLExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}finally{
if(conn!
=null){
try{
conn.close();
}catch(SQLExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
}
}
}
publicstaticvoidmain(String[]args){
Connectionconn=null;
PreparedStatementps=null;
ResultSetrs=null;
try{
conn=getConnection();
Stringsql="selectvalue_namefromsystem_value";
ps=conn.prepareStatement(sql);
rs=ps.executeQuery(sql);
while(rs.next()){
System.out.println(rs.getString("value_name"));
}
}catch(SQLExceptione){
e.pri