浅析Trafodion体系结构

Trafodion简介 php

    Trafodion是一个构建在Hadoop/HBase基础之上的关系型数据库,它彻底开源免费。Trafodion可以完整地支持ANSI SQL,而且提供ACID事务保证。和传统关系数据库不一样的地方在于,Trafodion利用底层Hadoop的横向扩展能力,能够提供极高的扩展性。而传统数据库,好比MySQL,在数据量达到P级别的时候就很难处理。而Trafodion却能够借助HBase的扩展性,仅经过增长普通Linux服务器就能够增长计算和存储能力,进而支持大数据应用。 java

好比原来使用MySQL的用户,若是数据量持续增长,每每须要采用先后端cache,分库分表,读写分离等技术。可是这些技术带来的弊端也不少。好比分库分表的构架下,不一样分库之间没法执行join操做。采用这些复杂技术后,系统结构复杂,维护和开发成本提升。这是不少客户正在面临的问题。 git

而从使用开发的角度来看,Trafodion和MySQL是彻底同样的,他们一样是关系型数据库,基本的功能彻底一致。所以一个经典的LAMP网络应用也能够轻松地用LATP(Linux, Apache, Trafodion, PHP) 搭建。而采用Trafodion,当业务扩展时,经过增长节点就能够应付不断增长的数据量,应用程序无需作任何修改,也无需考虑复杂的分库分表,读写分离等技术。这样就极大地下降了系统的复杂度。 github

这只是Trafodion的可能应用之一,Trafodion仍是一个很是适合的实时大数据分析平台。由于它不只能够支持实时分析,并且可以支持实时数据写入,好比每秒上万条的随机数据插入。这是构建实时分析所必备的能力。Stinger或者Impala虽然能够提供实时查询,但去没法支持实时的数据插入。 web

好比交通实时分析,利用Stinger/Impala等技术,虽然查询和分析能够在1分钟内完成,可是数据却只能按期载入,若是1小时一次,那么分析的数据样本是1小时前的数据,其分析结果也失去了时效性。好比,用户已经在那里堵车堵了了1个小时。 算法

关于Trafodion的使用场景读者能够参阅其余介绍Trafodion的系列文章。本文简要介绍Trafodion的技术体系结构,帮助读者基本了解Trafodion内部运做的原理。 数据库

读者还能够参考https://wiki.trafodion.org/wiki/index.php/Architecture了解Trafodion的技术构架。 后端

 

整体结构 缓存

    Trafodion的体系结构能够看做三层:ODBC接入层;SQL编译执行层;数据访问和存储层。其整体结构以下所示: 安全

客户端应用经过JDBC/ODBC访问Trafodion。客户链接由Trafodion的接入层负责。接入层为每个客户端链接分配一个master执行器,master负责用户链接全部query请求的执行和结果返回。对于简单的Query,Master进程自己就充当SQL执行层;复杂的query,访问大量数据和进行复杂运算的状况下,Master会启动一系列的ESP(Executor Server Processes)进程进行大规模并发执行。ESP进程是能够常驻内存的,以免启动开销,但若是长期处于空闲状态ESP进程会退出,释放资源。每一个ESP将执行结果返回给Master,由Master汇总并将最终结果返回给客户端。当Master或者ESP须要访问数据层的时候,会经过DTM来进行事务管理,在DTM(分布式事务管理器)的控制下调用HBase的客户端API进行数据的读写。下面分别介绍每一层的更多细节。

Trafodion的接入层

    接入层的主要组件有两个:DCSMaster和MXOSRVR 。DCS Master进程运行在Trafodion集群的单个节点上,负责监听客户端的链接请求。当收到请求后,DCSMaster根据集群的工做负载平衡状况,选定集群中一个节点上的MXOSRVR 做为客户端的执行代理。DCS Master将选定的MXOSRVR信息返回客户端,收到信息后,客户端直接和MXOSRVR 进行链接,此后客户端的全部请求都由该MXOSRVR 负责处理。相似Oracle的Dedicated 模式。

    当多个客户端请求链接时,DCSMaster会平均地将客户端链接到不一样的MXOSRVR ,从而均衡地利用集群中的每一个计算节点。并且每一个客户端都有一个单独的MXOSRVR 负责其后续计算请求的执行,以保证快速的响应客户query。一些数据库系统只有单一的ODBC接入点,高并发的状况下,就会出现排队现象,而采用了以上的模型后,每一个客户端都由一个接入点惟一负责,并且这些接入点平均分配在集群的各个节点,能够充分发挥每台计算节点的能力。

    为了下降延迟,Trafodion启动的时候会预先在每一个节点启动必定数量的MXOSRVR 进程。这样客户端链接请求被处理时,就不须要启动新MXOSRVR 进程的开销。可是Trafodion也不会预先启动很是多的MXOSRVR ,以避免在链接请求很少的状况下浪费资源。当客户请求数量大于预先启动的MXOSRVR 进程数目时,DCS Master再为新的链接请求启动新的MXOSRVR ,以便知足高并发的客户链接。

    DCS Master是全部客户端的惟一接入点,所以Trafodion为其提供了HA保护。当DCS Master故障退出,或者其所在节点崩溃时,Trafodion会在集群的其余健康节点上从新启动一个新的DCS Master,并利用floating IP的技术保证客户端能够继续执行链接。整个过程对客户端彻底透明。

    Trafodion的HA机制很是复杂,须要一篇单独的文章来详细介绍,这里就再也不展开叙述。

 

SQL编译执行层

    客户请求被接受后,每一个ODBC客户端都有一个单独的MXOSRVR 负责。该MXOSRVR 就是master进程,负责用户query的执行。一条用户query的执行流程大体以下:

    首先,MXOSRVR 会调用compiler模块对SQL语句进行编译和优化。Trafodion拥有一个很是成熟的SQL编译器,通过了20年的不断加强和改进,造成了一个强大的基于成本的优化器,可以生成用户SQL的最佳执行计划,好比最优的join表顺序。此外,编译器拥有一个执行计划缓存,若是SQL的执行计划已经在缓存中,则当即返回该计划,节省了编译的开销。

    执行计划会指导Master如何执行用户query。对于简单的query,执行计划仅仅须要master自己便可完成。对于复杂的query,master根据计划会启动多个ESP进程,并发地执行query。Trafodion的执行器是一个MPP构架的并发处理模型。它的多数执行操做符都支持并发,好比并发join,并发aggregation等等。

 

Trafodion编译器

    Trafodion编译器的主要职责就是将SQL文本解析为一个最优的执行计划。它主要包括如下几部分:

    Parser:parser采用bison对SQL文本进行文法分析,生成语法树。Parser也负责维护执行计划缓存。若是可以在这一步决定输入的SQL文本在缓存中,则直接返回执行计划。

    Binder:Binder对语法树进一步进行分析,相似程序编译器的语义分析,对语法合格的SQL进一步进行检查。好比检查Table是否存在,column数据类型是否匹配等。Binder还维护执行计划缓存。

    Normalizer:Normalizer对Binder生成的语法树进行逻辑优化。实施传统意义上的基于规则的优化,好比将查询条件下推;将子查询修改成semi-join;将DISTINCT转换为groupby等等。

    Analyzer:Analyzer对语法树进行一些补充,以帮助优化器判断是否能够运用某些规则。好比对于底层数据分区的访问能够有多种方式,能够直接从base table访问,或者从索引访问。Analyzer收集数据表的索引状况,添加进语法树,以便优化器作选择。

    Optimizer:能够说这是Trafodion最值得骄傲和关注的一个核心技术。优化器采用Cascades框架,是一个基于成本的优化器,并且Cascades框架很是易于扩展,开发人员能够添加新的规则来扩展新的优化方法。优化器实际上能够看做一个对问题空间的搜索过程,对于同一条query,经过规则,能够生成不少等价的执行计划。举一个例子:简单的规则,好比Ajoin B => B join A,应用该规则就会生成两个不一样的等价计划。

    优化器对语法树应用各类规则,生成不一样的执行计划,造成一个搜索空间。而后在这个搜索空间内经过比较每一个计划的成本,来找出最优的方案。因为规则众多,等价的执行计划数量会指数级增加,致使搜索空间很是巨大,所以采用穷举法一条一条的进行比较是不现实的。传统的优化器框架好比 Dynamic programming是自底向上的策略,很难缩小搜索空间,而Cascades采用自顶向下的搜索策略,能够很方便地利用branch-and-bound算法,将一些分支进行裁剪,即不须要再深刻分支进行优化。好比某分支的cost已经超出当前的总cost,则对于该分支就再也不进行进一步搜索。

    Cascades还拥有MEMO数据结构,可以记忆曾经搜索过的分支,这进一步增长了搜索的效率。

    此外Trafodion优化器还在多年的实践中总结出了不少的经验式规则(heuristics ),可以进一步减少搜索空间。

    最后优化器支持multi-pass的模式,对于简单的query,先enable很是少许的规则,将搜索空间限定在很小范围,所以能够高效地找到最优解;对于复杂query,进入第二个pass,enable全部的规则,进一步找出更好的执行计划。

    Pre-Code generator:optimizer选出了最优的执行计划,在生成物理执行计划以前,pre-codegenerator再应用一些物理优化策略,好比常数折叠,举例以下:假设Where条件为a=5 and b=a。 能够将b=a进一步替换为b=5。

    Generator:最后Generator将执行计划翻译为能够被Trafodion执行器执行的物理执行计划。这里有一个重要步骤,优化标量表达式。所谓标量表达式,即其解析结果为标量的表达式,好比a+b+c等。Trafodion利用LLVM将多数标量表达式编译成运行时的机器代码,从而进一步提升了执行速度,相似JIT将部分javabytecode编译为机器指令以便加速java程序的执行。

    成本模块:Trafodion编译器还有一个通过长期调节和校准的cost成本模块,对各类SQL operator的成本进行估计。成本计算须要对存放在表内数据的分布状况有所了解,这是依赖对表数据进行扫描和采样统计计算出的直方图来支持。成本模块从直方图中获得数据的分布状况,计算出Cardinality。它还综合考虑了CPU,内存消耗,消息通信和磁盘IO等条件为各个SQL操做算子计算出一个cost vector,提供比较准确的成本估计。

    以上各个系统组件协同工做,如上图所示,SQL语句通过parser和Normalizer的分析以后,输入优化器进行基于成本的优化;成本估计模块经过直方图得到数据分布,而后根据每一个操做符自身的特色,进行成本估计,将成本输入优化器。根据这些输入,优化器最终生成一个最优的执行计划。

 

Trafodion执行器

    Trafodion的执行器是一个MPP构架的并发执行器。它的工做模式是数据驱动,所以一旦有数据就绪,就能够返回用户,而无需等待整个query彻底结束执行,提升了用户响应速度。执行器由不一样的SQL操做符组成,数据在各个操做符之间经过IPC流动,无需将中间计算结果保存到磁盘。若是中间数据太大,超过了RAM的容量,操做符会将数据overflow到磁盘上,所以Trafodion的query执行不受物理内存大小限制。

 

并发执行

    Trafodion执行器最大的优势是极佳的并发能力。多数SQL操做算子都有并发执行的能力,包括GROUPBY,JOIN,INSERT都支持并发执行。

    这里举一个小例子来讲明Trafodion如何并发执行一个简单的sum(col1)汇集操做:master会在集群的每一个节点启动一个ESP进程,该进程负责对存储在该节点上的数据分区进行sum汇集操做。多个ESP同时并发执行,将最终结果发还给master,由master汇总。对于汇集,Trafodion还能够将该操做下推到数据访问层执行,而不须要将数据分区的每一行数据返回给ESP,由ESP逐一统计,而是由底层的数据访问层进行统计操做,仅仅将汇集结果发给ESP,ESP再返回给master。

    再看看Trafodion的Join。Trafodion支持全部的join类型,内链接,外链接,non-equijoin,semi-join,全链接等等。在Join的实现方式上,支持nestloop join,merge join和hashjoin。不管哪种join算法,都有并发执行的能力。Trafodion支持多种并发join方法,由优化器选择最优的一种。

首先介绍你们最熟悉的两种并发join算法,即broadcast和repartition。

broadcast parallel join(hash join)

broadcast类型的join中,一个表比较小,能够彻底放入单个节点的内存中。在这种状况下Trafodion会将小表广播到全部节点上。该并发执行方法用于hashjoin。每一个节点上的ESP将小表放入内存并创建hash表,而后顺序读入本节点上的大表分区,执行hashjoin操做。

repartition parallel join

repartition类型的join中,两个表都很大,没法放入单机内存。这种状况下,优化器生成的执行计划会自动派生两层ESP,第一层读取数据后按照join column进行repartition操做,将两个Join表的数据从新分区,将join column值相同的数据聚集到同一个第二层ESP中执行join操做。而后,全部的第二层ESP将Join结果返回master进行汇总。

以上两种在Hadoop的应用中常常被使用到,被称为mapper join和reducer join。这两种并发join方法都须要很是大的网络开销和内存开销。Trafodion优化器可以智能地在可能的状况下选择如下几种并发join方法:

Matching PartitionsJoin

若是参加join的两张表都是按照join column分区的,那么直接能够在各个节点的ESP中执行本地join,由于确定不须要其余节点上的数据。这是最理想的状况。

 

Inner Child ParallelAccess (for Nested Join)

这种方法只适用于Nest Loop Join。TblA做为outer table;TblB做为inner table。TblA有两个分区,所以启动2个ESP,ESP1从TblA的分区1逐行读取数据,而后逐一从TblB读取相应的数据行进行链接操做;同理ESP2也作一样的工做。这种类型的join比broadcast的方法节约内存开销,但多个ESP可能会竞争读取outer table。但能够支持非等值join。

 

Trafodion的MPP并发执行器还有不少其余的先进技术,好比HP的专利MDAM,Adaptive Segmentation,Skewbuster等均可以显著加速query的执行效率下降延迟,从而达到sub-second的实时响应。限于篇幅,MDAM等技术在这里就不展开叙述,Trafodion团队将陆续推出专题技术文章来单独介绍这些专利技术。

 

数据访问层

    当执行器对底层数据库表进行读写时,就须要调用数据访问层的服务。Trafodion的数据都存放在HBaseTable中。HBase自己支持对数据的随机读写,可是不支持ACID事务处理。所以数据访问层必须和DTM(分布式事务管理器)相互配合,实现有事务保护的读写。事务处理在下一个小结详细介绍。

    DTM对HBase的API进行了封装,添加了必要的事务处理支持。其他的读写逻辑和原生的HBase读写是同样的。所以若是不考虑事务,数据访问层就是一个标准的HBase客户端,经过HBaseclient API访问HBase。HBase是Trafodion数据访问和存储层的核心。也是Trafodion区别于传统数据库的最重要的地方。借助于HBase,Trafodion也能够提供极佳的水平扩展能力,同时具备很强的可靠性,而这些能力是传统数据库所不具有的。

 

    Trafodion支持的三种底层数据库表:Trafodion表,Hive表和HBase表。数据访问层须要负责对这三种存储类型的访问控制。

Trafodion表

    Trafodion表是用户用Trafodion的DDL语句直接建立的数据库表。在底层是一张HBase表,所以从Trafodion表到HBaseTable须要必定的映射和编码。

映射

    即如何将Trafodion数据库表映射到HBase Table。咱们考虑以下这个DDL建立的Trafodion表:

    create table sales.item(item_id int not null,

                          item_name char(10) ,

                          primary key (item_id));

    首先是如何将关系数据库的schame+table_name映射到HBaseTable。这个映射原则很是简单,即一个trafodion表在HBase中存储的表名为。例子中的item表在HBase中被映射为TRAFODION.SALES.ITEM这个HBaseTable。

    其次是Trafodion表的各个column如何映射到HBase的存储模式中。HBase的表内部有ColumnFamily,每一个ColumnFamily中能够有任意多的ColumnQualifier,每个行有一个rowkey,和一个timestamp。这四个维度定义了一个数据Cell。那么Trafodion的二维表如何映射到HBase这样的存储模型中呢?

    Trafodion将表的主键列组合起来做为HBase的rowkey。Column映射到HBase的columnqualifier,而timestamp被用做事务管理的时间戳。在目前的release中,全部列数据都存放在同一个ColumnFamily中,支持多ColumnFamily已经在Trafodion的蓝图中,所以将来这个映射会有所改变。

编码

    HBase存储的数据是没有数据类型的。Trafodion的表却支持不一样的SQL数据类型,好比CHAR型,即按字符串进行存储,”1”被编码为ASCII码0x41。若是SQL数据类型为INTEGER,在存储到HBase中时,Trafodion会直接写入二进制数0x00,0x00,0x00,0x01,占用4个byte;相应的LONG型占8个byte。

    Trafodion会自动进行类型处理,无需应用程序本身进行编解码的工做。

数据分区

    HBase会自动经过split技术对数据进行分区,可是某些状况下,好比时间序列数据顺序插入的状况下,大量的数据读写会集中在某个单一Region上,从而使得单台RegionServer的负载高于其余的RegionServer。Trafodion支持slatedpartition功能,在建立表的时候经过指定SALT关键字,Trafodion会自动为rowkey加入hash前缀,对表进行pre-split,保证平均地将数据分布在集群中。用户也能够不指定SALT关键字,而依赖底层HBase自动进行数据分区。

 

访问原生HBase表

    Trafodion也能够直接访问原生HBase表,提供两种访问方式: Cell-Per-Row和Rowwise Per-Row。

    经过Cell-Per-Row方式访问HBase表,每个HBase的Cell会做为SQL结果集中的一行数据。经过Rowwise Per-Row模式访问,每一行HBase数据做为SQL结果集的一行数据。

    假设Table1有2行数据,每行两个Cell:[(row1, CF1:Col1, v1), (row1,CF1:Col2, v2) , (row2, CF1:Col1, d1), (row2,CF1:Col2, d2)]。

Cell-Per-Row访问:

select * from hbase.”_CELL_”.”table1”       

返回4行数据

value

(row1, CF1:Col1, v1)

(row1,CF1:Col2, v2)

(row2, CF1:Col1, d1)

(row2, CF1:Col2, d2)

 

经过Rowwise-Per-Row方式访问:

select * from hbase.”_ROW_”.”table1”;

返回两行数据

rowkey

value

row1

CF1:Col1:v1 CF1:Col2:v2

row2

CF1:Col1:d1 CF1:Col2:d2

 

具体使用方法能够参考Trafodion的SQL Manual。

 

访问原生Hive表

    Trafodion能够直接访问原生Hive表。采用特殊的schema “hive”,用户直接使用SQL语句便可访问。好比

    select * fromhive.hive.table1;

    SQL引擎会识别”hive.hive”这个特殊的schema,读取Hive的metastore获取table1的元数据,而后直接经过libhdfs访问HDFS上的Hive表数据。所以绕过了DTM。因此,对于原生Hive表的访问,Trafodion不提供事务保护。

 

关于事务

    Trafodion的威尔士本意即事务,所以事务处理是Trafodion很是重要的一个方面。事务是一系列query的组合。一个事务由若干操做构成,并由begin开始,由commit或者abort结束。

    Trafodion采用两阶段提交协议来保证分布式事务的完整性。每一个节点均运行TM进程,全部的TM都是peerto peer对等的,而避免了单一的事务管理器的扩展性问题和SinglePoint of Failure问题。高并发状况下,全部的活跃事务由不一样节点上的TM分别管理,提供了很高的扩展能力。

    原生的HBase自己仅支持单行的ACID事务保证,Trafodion基于开源项目hbase-trx(https://github.com/hbase-trx/hbase-transactional-tableindexed)开发了目前版本的Transactionon HBase机制。提供了跨行跨表的ACID保证。hbase-trx采用MVCC机制,提供SnapShotIsolation事务隔离级别。原生的hbase-trx仅支持HBase0.94,且采用了侵入式的开发方法,大量修改了HBase的基本代码。Trafodion团队吸收了hbase-trx的基本思路,利用HBase协处理器从新开发了hbase-trx,并支持HBase0.98版本。并改进了日志实现,可以保证各类failure状况下数据的安全性。

    目前TrafodionDTM团队正在和中国科学院计算所合做开发新的Transactionon HBase算法Stateful-stateless Concurrency Control (SSCC)。关于SSCC的原理,读者能够进一步参考开源项目Domino:https://github.com/domino-succ/domino,预计将于TrafodionR1.2版本开始提供产品使用。SSCC提供比SnapShot Isolation更高级的隔离级别,同时对无状态写操做有很高效的支持,提供更高的并发度。无状态写在web应用中很是广泛,采用这一机制,Trafodion能够高效地为相关的web应用提供强大的支持。

 

小结

    Trafodion是一个复杂的大系统,一篇短文不管如何也不可能彻底说明其内部运做原理。笔者仅但愿用最简单的描述给各位读者一个大致的概念,做为一个开源项目,Trafodion欢迎各位研读源代码,并共同改进。

    经过本文,但愿读者认同如下几个关键点:

·        Trafodion有一个成熟的SQL编译器,可以进行基于成本的优化

·        Trafodion有一个先进的MPP并发执行引擎

·        Trafodion有一个创新的Transaction实现

·        Trafodion有一个成熟的ODBC/JDBC接入层

·        Trafodion构架在HBase之上,继承了全部HBase的优势。为用户提供极佳的水平扩展性

    本文没有涉及到的技术话题还有不少,好比Trafodion的HA实现,安全体系,NoSQL支持等。Trafodion团队会努力完善文档,也欢迎各位读者可以下载Trafodion源代码进行使用和学习,并贡献您的理解和分析。

相关文章
相关标签/搜索