负责2013年底数据库中间件设计研究笔记,分享拍拍给大家。1.什么是cobar?阿里开源的mysql中间件服务,使用mysql协议连接上游。Cobar是连接上游的传统mysql数据库。屏蔽后端分布式mysql集群。cobar属于前者。2、cobar应用场景举例逻辑上:数据库dbtest(虚拟)表tb1和tb2物理上:tb1表的数据在dbtest1(物理)的tb1上,tb2表的部分数据在dbtest2(物理)的tb2上,另一部分在dbtest3的tb2上(physical)3.cobar的使用方法命令行:连dbtest虚拟库JDBC:同样连接dbtest虚拟库查看db:可以看到dbtest1,dbtest2,dbtest3对用户是透明的。查看表:可以看到有两个表tb1和tb2。插入一些数据。对于用户来说,后端的分布式mysql是透明的:对于tb1来说,数据实际上是存储在dbtest1的tb1中对于tb2,数据实际上存储在dbtest2和dbtest3的tb2中画外音:从其官网查看,从2012年12月开始,cobar就没有再更新过,官方微博也很不活跃。不知道现在在阿里是怎么用的。如果你知道,请告诉我。4.cobar不支持什么?连接、分页、排序和子查询集语句将被忽略(事务和字符集设置除外)。无法更新分区密钥。不支持读写分离,不支持存储过程。如果使用JDBC、rewriteBatchedStatements、useServerPrepStmts、BLOB、BINARY和VARBINARY字段,则不能使用setBlob()或setBinaryStream()。分库实现支持一张表分库,支持不同表分库。注意:不支持将test拆分成test_1、test_2、test_3并放到同一个库中。画外音:后者正是360的atals所做的(atlas只支持单实例,单库分表)。2、HA:通过心跳到mysql,当主机挂掉时,主机自动切换回备机。但是当主机恢复时,需要手动切回检测主机和备机的异常,不关心主机和备机的数据同步(需要dba手动配置).画外音:需要注意,cobar需要用户自己实现负载均衡。有三种方式:自己用软件比如LVS,自己用硬件比如F5。cobar提供获取集群信息的命令,用户可以根据这些信息进行负载均衡;当然,淘宝已经实现了一款具有负载均衡功能的Cobar客户端产品——cobar.driver3。分库情况下的SQL路由,cobar会从SQL中提取partitionkey列,确定SQL路由到哪个分库执行;如果没有partitionkey,SQL会分发到所有的分库执行。4、例子tb1(idINT)假设数据按id分,后端分N个库:insertintotb1values(1);=>N个库会执行插入,因为没有partitionkey;insertintotb1(id)values(1);=>只会路由到1个库,有partitionkey;updatetb1setid=2whereid=1;=>不支持,不能修改partitionkey;画外音:带partitionkey的sql对cobar很重要,partitionkey是不支持修改的(修改库是错误的)。Cobar不允许在同一连接内切换库。画外音:数据库连接和库是绑定关系。不建议通过cobar执行DDL语句。画外音:所以要建数据库,建索引等,还是直接连接mysql,自己动手吧。5、COBAR自定义语句(1)查询cobar节点状态。cobar允许管理员通过管理命令上下线cobar节点。(2)查询cobar集群状态。定义了心跳将在cobar集群中的cobar节点之间发送。所谓心跳就是上面说的showcobra_status;所有cobar信息中的机会。当然,不显示离线或心跳超时的cobar节点信息。(3)查询SQL语句的路由状态。通过在SQL语句前加上explain,可以知道SQL语句的路由状态。6、事务支持Cobar对单个数据库保持事务强一致性。为分库维护事务的弱一致性。分库之后,事务提交包括两个阶段:执行阶段:SQL按照规则路由到多个分库。这时出现错误,commit阶段可以回滚:commit阶段出现错误,两个阶段无法正确回滚。执行和提交串行处理,stage内的各个子库并行处理。画外音:嗯,基本上不支持分布式事务。六、Cobar系统架构1.系统模块图画外音:从模块图来看,cobar的结构比较清晰:(1)前端到上游连接池(2)后端到下游mysql连接池(3)to每个请求都会经过:SQL解析,SQL路由,SQL执行,投递到后端mysql(4)对于每个响应,需要合并结果2.数据流图数据流图对应上面的模块图:3.网络模型采用异步网络模型:4.结果合并会将多个物理库的结果集进行合并,然后返回给上游:7.当cobar路由算法的partitionkey为int:时好办,直接取模当partitionkey为string时:f(string)=hash(string)%1024假设有4个库:hashresult0-255->library1hashresult256-511->library2hashresult512-767->library3hashresult768-1024->library4如何扩展:Hashresult0-255->库1拆分后:哈希结果0-127->库1.1哈希结果128-255->库1.2数据非均匀分布路由:哈希结果0-511(513范围)->Bank1哈希结果512-767(256范围)->Bank2hashresult768-895(128range)->Bank3hashresult896-1023(128range)->Library48.SQLforwardingbycobar1.Singlerecordquerywithpartitionkeyis直接根据分区键路由。2.带分区键的IN查询将IN拆分,将请求发送到对应的多个分库,然后合并结果集。3.不带partitionkey的where查询假设partitionkey是user字段,product字段的where查询会将请求广播到所有分库,然后合并结果集。4、二维分区键表的多个字段同时作为位置库的拆分字段。以上图中的visit(product,user,info)为例,可以同时使用product和user字段来定位图书馆。横坐标产品属性取hash,纵坐标用户属性取hash。SELECT*FROMvisitWHEREproduct='ColaCola'ANDuser='A'针对以上业务需求,以两列作为查询条件,可以直接定位7号馆。但是如果此时只使用其中一个字段作为查询条件,而不是查询多个库,然后聚合:SELECT*FROMvisitWHEREproduct='ColaCola'上面的业务需求,必须查询3、7、11、15库。画外音:不明白为什么双键路由用来。单键路由不会增加双键查询的数据扫描量。添加双密钥在某些情况下会使策略变得更加复杂,收益也会降低。不高。5.总结是的,对于where,cobar是这样处理的:根据字段的一致性hash分布,对数据进行多维拆分。根据where中的partitionkey,对查询SQL语句进行转换,分发到各个分库执行,合并结果。九。cobar的高级特性1.JOIN的有限处理如上,两张表都分库。JOIN要求如下:SELECT*FROMtb1INNERJOINtb2ONtb1.MEMBER_ID=tb2.NAME结果集应该如下:方案一:迭代查询FORrow1INselect*FROMtb1{ADD(SELECT*FROMtb2WHEREtb2.name=row1.member_id)TORESULT}画外音:让我去,外层循环是扫描一次tb1中的所有记录,而bt1的数据量很大,这怎么能容忍?二:Kwaku索引针对tb1和tb2潜在的JOIN需求,为JOIN列建立Kwaku索引。直接JOIN查询:Kua数据库索引建立后,直接JOIN查询是合并idx索引表中数据的结果。JOIN后的WHERE条件:SELECT*FROMtb1INNERJOINtb2ONtb1.MEMBER_ID=tb2.NAMEWHEREtb1.id=5此时需要改写SQL语句,直接在索引表上查询:此时需要改写SQL语句,直接在索引表上查询:SELECT*FROMidxWHEREid1=5这里注意:索引表的分区键:WHERE条件所在表的分区键,作为索引表的分区键,索引必须包含主键JOIN相关表,JOIN字段,字段索引的更新包括WHERE条件:需要分布式事务的支持2.GROUPBY处理上表为例,patitionkey为ID,进行GROUPBY对C1的操作:SELECTSUM(price)FROMtb1GROUPBYc1;改写SQL语句,先对每个分库GROUPBY一次,计算总和:SELECTSUM(price),c1FROMtb1GROUPBYc1ORDERBYc1;每个分库进行GROUPBY+ORDERBY+sum后,根据排序后的c1和对应的sum结果,合并一次后得到最终结果。3.小结对于复杂的语句,可以这样处理:对于JOIN,可以迭代查询,也可以使用分布式索引。对于GROUPBY,需要添加查询列,以及ORDERBY13末的研究笔记,文中的“画外音”是我当时的评论,希望大家对cobar有一个初步的了解,以及如有任何问题,欢迎交流。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文
