分布式RDBMS(Cobar)
cfer7367
9年前
来自: https://blog.huachao.me/2016/2/分布式RDBMS/
传统的关系型数据库在高并发,大数据的情况下性能会急剧降低,比如,一般MySQL的qps在10k以下,单表的数据量千万级已经封顶。有鉴于此,程序员,DBA们想到通过多台MySQL来分担大量的查询和分多台机器来存储,分布式RDBMS由此而生。
本文以阿里巴巴开源的 Cobar 为蓝本,简单叙述其设计的思想,要解决的问题,如果可能的话会简单解释一下其代码结构。注意目前阿里云上分布式关系型数据库的解决方案是 DRDS ,其使用的核心就是 Cobar 和 TDDL 。TDDL复杂度高,当前公布的文档较少,只开源动态数据源,分表分库部分还未开源,还需要依赖diamond,所以不讨论了。
Cobar能用来干啥
一图胜前言。对外表现为一个关系型数据库,对内将记录路由到各个工作DB,可以进行无限的水平扩展(scale out)。
Cobar也支持垂直拆分,即不同业务存储不同的database。
Cobar作为一个proxy怎么路由到各个工作DB
Cobar作为一个proxy,实现了接收客户端的链接和jdbc的协议,然后根据sql语句,查询路由定义,然后路由到工作DB的。
- schema定义, 注意: schema/table中的rule,即为这个表对应的拆分规则
<?xmlversion="1.0"encoding="UTF-8"?> <!DOCTYPEcobar:schemaSYSTEM"schema.dtd"> <cobar:schema xmlns:cobar="http://cobar.alibaba.com/"> <!--schema定义 --> <schema name="dbtest" dataNode="dnTest1"> <table name="tb2" dataNode="dnTest2,dnTest3" rule="rule1"/> </schema> <!--数据节点定义,数据节点由数据源和其他一些参数组织而成。--> <dataNode name="dnTest1"> <property name="dataSource"> <dataSourceRef>dsTest[0]</dataSourceRef> </property> </dataNode> <dataNode name="dnTest2"> <property name="dataSource"> <dataSourceRef>dsTest[1]</dataSourceRef> </property> </dataNode> <dataNode name="dnTest3"> <property name="dataSource"> <dataSourceRef>dsTest[2]</dataSourceRef> </property> </dataNode> <!--数据源定义,数据源是一个具体的后端数据连接的表示。--> <dataSource name="dsTest" type="mysql"> <property name="location"> <location>192.168.0.1:3306/dbtest1</location> <location>192.168.0.1:3306/dbtest2</location> <location>192.168.0.1:3306/dbtest3</location> </property> <property name="user">test</property> <property name="password"></property> <property name="sqlMode">STRICT_TRANS_TABLES</property> </dataSource> </cobar:schema>
- 拆分键定义
<?xmlversion="1.0"encoding="UTF-8"?> <!DOCTYPEcobar:ruleSYSTEM"rule.dtd"> <cobar:rulexmlns:cobar="http://cobar.alibaba.com/"> <!--路由规则定义,定义什么表,什么字段,采用什么路由算法。--> <tableRule name="rule1"> <rule> <columns>id</columns> <algorithm><![CDATA[func1(${id})]]></algorithm> </rule> </tableRule> <!--路由函数定义,应用在路由规则的算法定义中,路由函数可以自定义扩展。--> <function name="func1" class="com.alibaba.cobar.route.function.PartitionByLong"> <property name="partitionCount">2</property> <property name="partitionLength">512</property> </function> </cobar:rule>
Cobar的工作流程
同样的一图胜千言。
最佳实践
数据拆分策略
- 容量和访问均衡。拆分键能够使得记录均匀地分布到各个工作DB上。
- 事务边界。尽量地在一个工作DB上进行事务;如果涉及到多台工作DB,那么使用消息队列来达到最终一致性;分布式数据库事务会有严重的性能问题,只在必须的时候使用
数据库连接池
推荐使用阿里巴巴的 druid 作为数据库连接池。注意其中的url,要配置为proxy的ip,也就是Cobar机器所在的ip。
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <!-- 基本属性 url、user、password --> <property name="url" value="jdbc:mysql://ip:port/db?autoReconnect=true&rewriteBatchedStatements=true&socketTimeout=30000&connectTimeout=3000" /> <property name="username" value="root" /> <property name="password" value="123456" /> <!-- 配置初始化大小、最小、最大 --> <property name="maxActive" value="20" /> <property name="initialSize" value="3" /> <property name="minIdle" value="3" /> <!-- maxWait获取连接等待超时的时间 --> <property name="maxWait" value="60000" /> <!-- timeBetweenEvictionRunsMillis间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- minEvictableIdleTimeMillis一个连接在池中最小空闲的时间,单位是毫秒--> <property name="minEvictableIdleTimeMillis" value="300000" /> <property name="validationQuery" value="SELECT 'z'" /> <property name="testWhileIdle" value="true" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> </bean>