http://hualong.iteye.com/blog/2102798
这几天研究了下Cobar, Cobar是阿里巴巴研发的关系型数据的分布式处理系统(Amoeba的升级版,该产品成功替代了原先基于Oracle的数据存储方案,目前已经接管了3000+个MySQL数据库的schema,平均每天处理近50亿次的SQL执行请求。)(github上面的是源码,大家下来需要自己用maven2编译后运行、者放Eclipse里面运行,一开始我用maven3没有执行成功。)
首先,使用Cobar的核心功能如下:分布式:Cobar的分布式主要是通过将表放入不同的库来实现:1. Cobar支持将一张表水平拆分成多份分别放入不同的库来实现表的水平拆分2. Cobar也支持将不同的表放入不同的库3. 多数情况下,用户会将以上两种方式混合使用这里需要强调的是,Cobar不支持将一张表,例如test表拆分成test_1, test_2, test_3.....放在同一个库中,必须将拆分后的表分别放入不同的库来实现分布式。HA:在用户配置了MySQL心跳的情况下,Cobar可以自动向后端连接的MySQL发送心跳,判断MySQL运行状况,一旦运行出现异常,Cobar可以自动切换到备机工作。但需要强调的是:1. Cobar的主备切换有两种触发方式,一种是用户手动触发,一种是Cobar的心跳语句检测到异常后自动触发。那么,当心跳检测到主机异常,切换到备机,如果主机恢复了,需要用户手动切回主机工作,Cobar不会在主机恢复时自动切换回主机,除非备机的心跳也返回异常。2. Cobar只检查MySQL主备异常,不关心主备之间的数据同步,因此用户需要在使用Cobar之前在MySQL主备上配置双向同步,详情可以参阅MySQL参考手册。其次,我们也需要注意Cobar的功能约束:1) 不支持跨库情况下的join、分页、排序、子查询操作。2) SET语句执行会被忽略,事务和字符集设置除外。3) 分库情况下,insert语句必须包含拆分字段列名。4) 分库情况下,update语句不能更新拆分字段的值。5) 不支持SAVEPOINT操作。6) 暂时只支持MySQL数据节点。7) 使用JDBC时,不支持rewriteBatchedStatements=true参数设置(默认为false)。8) 使用JDBC时,不支持useServerPrepStmts=true参数设置(默认为false)。9) 使用JDBC时,BLOB, BINARY, VARBINARY字段不能使用setBlob()或setBinaryStream()方法设置参数。然后,我们来分析一下Cobar逻辑层次图: * dataSource:数据源,表示一个具体的数据库连接,与物理存在的数据库schema一一对应。* dataNode:数据节点,由主、备数据源,数据源的HA以及连接池共同组成,可以将一个dataNode理解为一个分库。* table:表,包括拆分表(如tb1,tb2)和非拆分表。* tableRule:路由规则,用于判断SQL语句被路由到具体哪些datanode执行。* schema:cobar可以定义包含拆分表的schema(如schema1),也可以定义无拆分表的schema(如schema2)。Cobar支持的数据库结构(schema)的层次关系具有较强的灵活性,用户可以将表自由放置不同的datanode,也可将不同的datasource放置在同一MySQL实例上。在实际应用中,我们需要通过配置文件(schema.xml)来定义我们需要的数据库服务器和表的分布策略,这点我们将在后面的安装和配置部分中介绍到。接着,我们来介绍Cobar的安装和配置步骤:下面我们将使用一个最简单的分库分表的例子来说明Cobar的基本用法,数据库schema如下图(该实例也可参考:)。 1) 系统对外提供的数据库名是dbtest,并且其中有两张表tb1和tb2。2) tb1表的数据被映射到物理数据库dbtest1的tb1上。3) tb2表的一部分数据被映射到物理数据库dbtest2的tb2上,另外一部分数据被映射到物理数据库dbtest3的tb2上。1、环境准备操作系统:Linux或者Windows (推荐在Linux环境下运行Cobar)MySQL: (推荐使用5.1以上版本)JDK: (推荐使用1.6以上版本)Cobar:https://github.com/alibaba/cobar (下载tar.gz或者zip文件,特意说明下,阿里的开源全部移到github上去了,里面有很多阿里人的作品,当然包含著名的dubbo,地址是:)2、数据准备假设本文MySQL所在服务器IP为192.168.0.1,端口为3306,用户名为test,密码为空,我们需要创建schema:dbtest1、dbtest2、dbtest3,table:tb1、tb2,SQL如下:[sql] copy
1. #创建dbtest1
2. drop database if exists dbtest1;
3. create database dbtest1;
4. use dbtest1;
5. #在dbtest1上创建tb1
6. create table tb1(
7. id int not null,
8. gmt datetime);
9.
10.#创建dbtest2
11.drop database if exists dbtest2;
12.create database dbtest2;
13.use dbtest2;
14.#在dbtest2上创建tb2
15.create table tb2(
16.id int not null,
17.val varchar(256));
18.
19.#创建dbtest3
20.drop database if exists dbtest3;
21.create database dbtest3;
22.use dbtest3;
23.#在dbtest3上创建tb2
24.create table tb2(
25.id int not null,
26.val varchar(256));
[html]
1. <?xml version="1.0" encoding="UTF-8"?>
2. <!DOCTYPE cobar:schema SYSTEM "schema.dtd">
3. <cobar:schema xmlns:cobar="http://cobar.alibaba.com/">
4.
5. <!-- schema定义 -->
6. <schema name="dbtest" dataNode="dnTest1">
7. <table name="tb2" dataNode="dnTest2,dnTest3" rule="rule1" />
8. </schema>
9.
10. <!-- 数据节点定义,数据节点由数据源和其他一些参数组织而成。-->
11. <dataNode name="dnTest1">
12. <property name="dataSource">
13. <dataSourceRef>dsTest[0]</dataSourceRef>
14. </property>
15. </dataNode>
16. <dataNode name="dnTest2">
17. <property name="dataSource">
18. <dataSourceRef>dsTest[1]</dataSourceRef>
19. </property>
20. </dataNode>
21. <dataNode name="dnTest3">
22. <property name="dataSource">
23. <dataSourceRef>dsTest[2]</dataSourceRef>
24. </property>
25. </dataNode>
26.
27. <!-- 数据源定义,数据源是一个具体的后端数据连接的表示。-->
28. <dataSource name="dsTest" type="mysql">
29. <property name="location">
30. <location>192.168.0.1:3306/dbtest1</location> <!--注意:替换为您的MySQL IP和Port-->
31. <location>192.168.0.1:3306/dbtest2</location> <!--注意:替换为您的MySQL IP和Port-->
32. <location>192.168.0.1:3306/dbtest3</location> <!--注意:替换为您的MySQL IP和Port-->
33. </property>
34. <property name="user">test</property> <!--注意:替换为您的MySQL用户名-->
35. <property name="password">test</property> <!--注意:替换为您的MySQL密码-->
36. <property name="sqlMode">STRICT_TRANS_TABLES</property>
37. </dataSource>
38.</cobar:schema>
我们注意到,上述配置实际上已经把图2中的数据库结构配置好了。dbtest主要映射的是dnTest1库(即192.168.0.1:3306/dbtest1库),而其中的tb2表则是按照规则rule1,被分配到dnTest2库(即192.168.0.1:3306/dbtest2库)和dnTest3库(即192.168.0.1:3306/dbtest3库)中。此外,规则rule1的定义可以在rule.xml中找到,代码如下:
[html]
1. <?xml version="1.0" encoding="UTF-8"?>
2. <!DOCTYPE cobar:rule SYSTEM "rule.dtd">
3. <cobar:rule xmlns:cobar="http://cobar.alibaba.com/">
4.
5. <!-- 路由规则定义,定义什么表,什么字段,采用什么路由算法。-->
6. <tableRule name="rule1">
7. <rule>
8. <columns>id</columns>
9. <algorithm><![CDATA[ func1(${id})]]></algorithm>
10. </rule>
11. </tableRule>
12.
13. <!-- 路由函数定义,应用在路由规则的算法定义中,路由函数可以自定义扩展。-->
14. <function name="func1" class="com.alibaba.cobar.route.function.PartitionByLong">
15. <property name="partitionCount">2</property>
16. <property name="partitionLength">512</property>
17. </function>
18.</cobar:rule>
结合schema.xml中的内容,我们可以看出分表的规则是,按照id字段把tb2表中的数据分配到dnTest2和dnTest3两个分区中,其中id小于512的数据会被放到dnTest2库的分区中,而其余的会被放到dnTest3库的分区中,更多路由算法可以参考《》。最后,我们来看一下server.xml的配置,代码如下。
[html]
1. <?xml version="1.0" encoding="UTF-8"?>
2. <!DOCTYPE cobar:server SYSTEM "server.dtd">
3. <cobar:server xmlns:cobar="http://cobar.alibaba.com/">
4.
5. <!--定义Cobar用户名,密码-->
6. <user name="root">
7. <property name="password">passwd</property>
8. <property name="schemas">dbtest</property>
9. </user>
10.</cobar:server>
这里的server.xml配置比较简单,只配置了本地Cobar服务的数据库结构、用户名和密码。在启动Cobar服务之后,使用用户名root和密码passwd就可以登录Cobar服务。
4、运行Cobar启动Cobar服务很简单,运用bin目录下的start.sh即可(停止使用shutdown.sh)。启动成功之后,可以在logs目录下的stdout.log中看到如下日志:[html]
1. 10:54:19,264 INFO ===============================================
2. 10:54:19,265 INFO Cobar is ready to startup ...
3. 10:54:19,265 INFO Startup processors ...
4. 10:54:19,443 INFO Startup connector ...
5. 10:54:19,446 INFO Initialize dataNodes ...
6. 10:54:19,470 INFO dnTest1:0 init success
7. 10:54:19,472 INFO dnTest3:0 init success
8. 10:54:19,473 INFO dnTest2:0 init success
9. 10:54:19,481 INFO CobarManager is started and listening on 9066
10.10:54:19,483 INFO CobarServer is started and listening on 8066
11.10:54:19,484 INFO ===============================================
[html]
1. ... ...
2. <!-- 数据节点定义,数据节点由数据源和其他一些参数组织而成。-->
3. <dataNode name="dnTest1">
4. <property name="dataSource">
5. <dataSourceRef>dsTest[0]</dataSourceRef>
6. </property>
7. <!--Cobar与后端数据源连接池大小设置-->
8. <property name="poolSize">256</property>
9. <!--Cobar通过心跳来实现后端数据源HA,一旦主数据源心跳失败,便切换到备数据源上工作-->
10. <!--Cobar心跳是通过向后端数据源执行一条SQL语句,根据该语句的返回结果判断数据源的运行情况-->
11. <property name="heartbeat">select user()<property>
12. </dataNode>
13.... ...
2、当我们需要对Cobar作集群(cluster),进行负载均衡的时候,我们也需要用到心跳机制。不过此处的配置则是在server.xml中,代码如下:
[html]
1. ... ...
2. <!--组建一个Cobar集群,只需在cluster配置中把所有Cobar节点(注意:包括当前Cobar自身)都配置上便可-->
3. <cluster>
4. <!--node名称,一个node表示一个Cobar节点,一旦配置了node,当前Cobar便会向此节点定期发起心跳,探测节点的运行情况-->
5. <node name="cobar1">
6. <!--Cobar节点IP, 表示当前Cobar将会向192.168.0.1上部署的Cobar发送心跳-->
7. <property name="host">192.168.0.1</property>
8. <!--节点的权重,用于客户端的负载均衡,用户可以通过命令查询某个节点的运行情况以及权重-->
9. <property name="weight">1</property>
10. </node>
11. <!--当前Cobar将会向192.168.0.2上部署的Cobar发送心跳-->
12. <node name="cobar2">
13. <property name="host">192.168.0.2</property>
14. <property name="weight">2</property>
15. </node>
16. <!--当前Cobar将会向192.168.0.3上部署的Cobar发送心跳-->
17. <node name="cobar3">
18. <property name="host">192.168.0.3</property>
19. <property name="weight">3</property>
20. </node>
21. <!--用户还可以将Cobar节点分组,以便实现schema级别的细粒度负载均衡-->
22. <group name="group12">
23. <property name="nodeList">cobar1,cobar2</property>
24. </group>
25. <group name="group23">
26. <property name="nodeList">cobar2,cobar3</property>
27. </group>
28. </cluster>
29.... ...
最后说点题外话,目前国内关于mysql分布式中间有
360公司的Atlas:
淘宝的tddl:
京东的蓝海豚:
网易的DDB:
但是还是阿里的cobar好些,因为他开源了,除了中间件本身,还开源提供驱动、管理器。