首页 > > > 阿里分布式数据库DRDS
DRDS将TDDL和Cobar整合起来,从2012年开始发展到现在,功能已经非常成熟。除了将后端数据库聚合成一个逻辑库,提供数据垂直拆分、水平拆分、读写分离等功能外,还具备功能比较齐全的分布式SQL查询、优化、执行引擎,提供分布式事务管理方案,等等,DRDS已经不是一个简单的数据库代理、分库分表中间件,已经发展为分布式数据库引擎。将后端数据库看作一个高级版存储引擎,DRDS则可以看作数据库的执行引擎,DRDS集群和后端数据库集群共同组成一个分布式数据库。



参考SQL调优基础概念、查询优化器介绍、查询执行器介绍、执行计划和基本算子、Join与子查询的优化和执行等。
结合后端数据库,DRDS形成了一个比较完整的查询执行引擎,某些方面比MySQL方案更多:
concurrent是并发而非并行,指多线程执行分片查询,将结果集汇总):HashAgg(group="l_orderkey", revenue="SUM(*)") HashJoin(condition="o_custkey = c_custkey", type="inner") Gather(concurrent=true) LogicalView(tables="ORDERS_[0-7],LINEITEM_[0-7]", shardCount=8, sql="SELECT `ORDERS`.`o_custkey`, `LINEITEM`.`l_orderkey`, (`LINEITEM`.`l_extendedprice` * (? - `LINEITEM`.`l_discount`)) AS `x` FROM `ORDERS` AS `ORDERS` INNER JOIN `LINEITEM` AS `LINEITEM` ON (((`ORDERS`.`o_orderkey` = `LINEITEM`.`l_orderkey`) AND (`ORDERS`.`o_orderdate` < ?)) AND (`LINEITEM`.`l_shipdate` > ?))") Gather(concurrent=true) LogicalView(tables="CUSTOMER_[0-7]", shardCount=8, sql="SELECT `c_custkey` FROM `CUSTOMER` AS `CUSTOMER` WHERE (`c_mktsegment` = ?)")DRDS SQL执行过程:

查询优化器:
执行计划缓存:

所有算子都定义了open()、next()等接口,算子根据执行计划组合成一棵算子树,上层算子通过调用下层算子的next()接口的取出结果,完成该算子的计算。最终顶层算子产生用户需要的结果并返回给客户端。

查询优化最有效的措施是尽可能将操作下推给后端数据库,避免DRDS内的操作。一些简单、可以落在单库执行的SQL,可以整条语句下推给后端数据库;复杂查询则尽可能多的将子操作-算子下推,不能下推的部分由DRDS执行器处理:

示例SQL:
SELECT l_orderkey, sum(l_extendedprice *(1 - l_discount)) AS revenue
FROM CUSTOMER, ORDERS, LINEITEM
WHERE c_mktsegment = 'AUTOMOBILE' and c_custkey = o_custkey and l_orderkey = o_orderkey
and o_orderdate < '1995-03-13' and l_shipdate > '1995-03-13'
GROUP BY l_orderkey;EXPLAIN展示的DRDS执行计划:
HashAgg(group="l_orderkey", revenue="SUM(*)")
HashJoin(condition="o_custkey = c_custkey", type="inner")
Gather(concurrent=true)
LogicalView(tables="ORDERS_[0-7],LINEITEM_[0-7]", shardCount=8, sql="SELECT `ORDERS`.`o_custkey`, `LINEITEM`.`l_orderkey`, (`LINEITEM`.`l_extendedprice` * (? - `LINEITEM`.`l_discount`)) AS `x` FROM `ORDERS` AS `ORDERS` INNER JOIN `LINEITEM` AS `LINEITEM` ON (((`ORDERS`.`o_orderkey` = `LINEITEM`.`l_orderkey`) AND (`ORDERS`.`o_orderdate` < ?)) AND (`LINEITEM`.`l_shipdate` > ?))")
Gather(concurrent=true)
LogicalView(tables="CUSTOMER_[0-7]", shardCount=8, sql="SELECT `c_custkey` FROM `CUSTOMER` AS `CUSTOMER` WHERE (`c_mktsegment` = ?)")
LogicalView都是下推给后端数据库的操作;ORDERS和LINEITEM为父子关系表,因此可以将这2个表的关联查询下推给各个分片;CUSTOMER与ORDERS的关联无法由数据库完成,由DRDS汇总(Gather)2个结果集后在内存中执行HashJoin;HashAgg进行聚合计算;概念参考DRDS全局二级索引。在Mycat分库分表概览中也创建了自定义索引表,在应用代码中维护。DRDS支持全局二级索引GSI,自动维护:

数据写入时通过XA多写维护GSI,并确保数据强一致性。回表:即数据库的RID lookup。
DRDS扩展了MySQL DDL语法来管理GSI,参考DRDS全局二级索引使用文档,支持索引类型BTREE、HASH。

DRDS支持的平滑扩容实现方式:在同一个后端RDS实例上创建多个MySQL数据库(默认8个),RDS实例负载、存储空间过高时,申请新的RDS实例,将部分MySQL数据库迁移到新的RDS实例上,参考DRDS 平滑扩容。
参考DRDS分布式事务:
阿里分布式事务发展情况:
事务消息、XTS都要求业务代码实现大量事务控制逻辑(事务状态回查、事务补偿,以及TCC中的Try-Confirm等),对一线开发人员要求高,容易造成数据不一致问题。
DRDS的分布式事务与GTS的关系和区别:
DRDS全局唯一数字序列,参考DRDS Sequence介绍,使用限制参考Sequence限制及注意事项。
两类用法:
select seq.nextval取值;AUTO_INCREMENT,DRDS将自动维护全局Sequence;DRDS主要是利用MySQL全局表来生成全局序列,Sequence类型:
Group Sequence原理:
假设sequence名称为my_seq,共3个分组,内步长1000,初始值如下:
+---------------+------------+---------------+
| sequence_name | group_name | current_value |
+---------------+------------+---------------+
| my_seq | group_0 | 0 |
| my_seq | group_1 | 1000 |
| my_seq | group_2 | 2000 |
+---------------+------------+---------------+某节点需要分配下一个sequence值时:
group_1,则得到sequence当前值1000;group_1的当前值更新:(1000, 2000]取走,因为设置了3个分组,外步长=内步长*3,所以将sequence当前值更新为4000:+---------------+------------+---------------+ | sequence_name | group_name | current_value | +---------------+------------+---------------+ | my_seq | group_0 | 0 | | my_seq | group_1 | 4000 | | my_seq | group_2 | 2000 | +---------------+------------+---------------+(1000, 2000],当前sequence值到达2000后,重新按步骤申请下一个号段;节点中途停机退出,已经申请的号段中没有使用的值被丢弃,不再使用。原文作者:;如有侵权,请联系管理员删除。