火实时大数据 OLAP 技术原理和实践

更新时间:2017-09-15 09:12:36 点击次数:1934次

Druid是什么


Druid在大数据领域已经不是新人了,因此可能很多读者都已经听说过Druid,甚至用过Druid,但是未必每个人都真正清晰地了解Druid到底是什么,以及在什么情况下可以用Druid。同时,为了避免大家听了半天,却一直陷在各种细节中但仍然不知道到底在听什么东西,我们还是有必要在开始的时候先总体谈一谈Druid到底是什么。


简单来说,Druid 是一个分布式的、支持实时多维OLAP分析的数据处理系统。它既支持高速的数据实时摄入处理,也支持实时且灵活的多维数据分析查询。因此Druid常用的场景就是大数据背景下、灵活快速的多维OLAP分析。 另外,Druid还有一个关键的特点:它支持根据时间戳对数据进行预聚合摄入和聚合分析,因此也有用户经常在有时序数据处理分析的场景中用到它。


Druid用户群能够迅速发展的一个原因是它在大数据背景下集群依然具备的性能和可扩展性。Imply.io公司是Druid创始人创办的公司,我们可以先通过它公布的一些集群性能介绍图片来概览一下Druid集群的一些特点。


数据实时消费能力:



集群的数据规模:



查询速度:



查询的并发量:



不难看出,Druid集群在大数据场景下表现优异。


接下来,我们也顺便聊一聊Druid的历史。Druid 单词来源于西方古罗马的神话人物, 中文常常翻译成德鲁伊。传说 Druid 教士精通占卜, 对祭祀礼仪一丝不苟,也擅长于天文历法、医药、天文和文学等。同时, Druid 也 是执法者、吟游诗人和探险家的代名词。美国广告技术公司 MetaMarkets 于 2011 年创建了 Druid 项目, 并且于 2012 年开源了 Druid 项目。 Druid 设计之初的想法就是为分析而生,它在处理数据的规模、数据处理的实时性方面, 比传统的 OLAP 系统有了显著的性能改进, 而且拥抱主流的开源生态, 包括 Hadoop 等。多年以来, Druid 一直是非常活跃的开源项目。 另外, 阿里巴巴也曾创建过一个开源项目叫作 Druid(简称阿里 Druid), 它是一个数据库连接池的项目。阿里 Druid 和本书讨论的 Druid 没有任何关系,它们解决完全不同的问题。


Druid 的官方网站是 http://druid.io。



技术选型的思考


各个公司在技术选型的时候都会货比三家,因此在考察Druid的时候也一定会问为什么需要选择Druid。在本段落中,我们将会对用户经常会拿来和Druid做比较的组件中的其中几个来做一些简单的说明。但是在比较之前,我需要阐明一个基本的观点:这些不同组件或技术有各自的特点和适用范围,并没有一个技术就能彻底替代其它技术这种说法,而本文就仅拿“大数据量下的实时多维OLAP分析”这一场景来做比较。


传统关系型数据库:



传统关系型数据库(RDBMS)历史久远、技术成熟,应用者广泛,因此采用的学习成本和技术风险也相对较低。典型的RDBMS有Oracle、DB2和MySQL等。从理论上讲,因为RDBMS能保证数据的立即一致性,因此特别适合OLTP的场景。然而由于自身的特点所限,RDBMS在可扩展性方面却表现欠佳,很难轻易和低成本低进行线性扩展以处理更大的数据量。即便现在大多数据库可以通过分库分表等方法来使自己可以容纳更多的数据,但是这种方式也存在着管理复杂和成本高昂等明显短板,因此实际应用中也存在着数据量的天花板。因此,考虑既定的场景“大数据量下的实时多维OLAP分析”,RDBMS首先就很难跨过“大数据量”这一关。


Massively Parallel Processing 数据库:



大规模并行处理(MPP,massively parallel processing)数据库的代表是Teradata、Greenplum、Vertica和Impala等。它们的优点是适合将RDBMS的应用扩展到集群范围,以处理更大的数据量,同时继承了RDBMS的很多优点。然而,它依然没法从根本上满足处理海量数据的需求,因为它的系统性能很难随集群的扩展一直线性增长,所以其集群扩展性有限;而且它的集群容错性也有限,比如当其Raid磁盘出错后可能会导致其节点响应速度变慢。


ElasticSearch:



ElasticSearch几乎已经是当下实时上的搜索服务器标准,而它与Logstash和Kibana的搭配(简称ELK)也是应用很广的套件组合。ElasticSearch有很强的文档索引和全文检索的能力,也支持丰富的查询功能(包括聚合查询),并且扩展性好,因此很多用户也常常在拿Elasticsearch和Druid做比较。然而,在我们的既定场景下,Elasticsearch有着其明显的短板:不支持预聚合;组合查询性能欠佳;等等。


OpenTSDB:



OpenTSDB是一款的时序数据库,且基于用户广泛的HBase数据库,因此有着较多的客户群。它的优势在于查询速度快、扩展性好,且schemaless。然而,它也有一些缺点:查询的维度组合数量需要提前确定好,即通过存储中的tag组合来确定,因此缺乏了灵活性;数据冗余度大;基于HBase,对于运维人员能力要求较高;等等。


Kylin:



Kylin出自eBay,并且是Apache的新顶级项目,是一款非常不错的分布式OLAP系统。它的优势在于项目来自于丰富的实践、发展前景光明、直接利用了成熟的Hadoop体系(HBase和Hive等)、cube模型支持较好、查询速度快速等。但它也在一些方面有着自己的局限,比如:查询的维度组合数量需要提前确定好,不适合即席查询分析;预计算量大,资源消耗多;集群依赖较多,如HBase和Hive等,属于重量级方案,因此运维成本也较高;等等。


Druid基础知识


数据存储格式


Druid自己有着数据存储的逻辑和格式(主要是DataSource和Segment),而且其架构和实现也是围绕着它们而进行的,因此我们有必要对其数据存储格式做一些介绍。


首先,若与传统的关系型数据库管理系统(RDBMS)做比较,Druid 的 DataSource 可以理解为 RDBMS 中的表(Table)。正如前面章节中所介绍的,DataSource 的结构包含以下几个方面。




无论是实时数据消费还是批量数据处理,Druid 在基于 DataSource 结构存储数据时即可选择对任意的指标列进行聚合(Roll Up)操作。相对于其他时序数据库,Druid 在数据存储时便可对数据进行聚合操作是其一大特点, 并且该特点使得 Druid 不仅能够节省存储空间,而且能够提高聚合查询的效率。


DataSource 是一个逻辑概念,Segment 却是数据的实际物理存储格式,Druid 正是通过 Segment 实现了对数据的横纵向切割(Slice and Dice)操作。从数据按时间分布的角度来看, 通过参数 segmentGranularity 的设置,Druid 将不同时间范围内的数据存储在不同的 Segment 数据块中,这便是所谓的数据横向切割。这种设计为 Druid 带来一个显而易见的优点:按时间范围查询数据时,仅需要访问对应时间段内的这些 Segment 数据块,而不需要进行全表数据范围查询,这使效率得到了极大的提高。



同时,在 Segment 中也面向列进行数据压缩存储,这便是所谓的数据纵向切割。而且对Segment 中的维度列使用了 Bitmap 技术对其数据的访问进行了优化。其中,Druid会为每一维度列存储所有列值、创建字典(用来存储所有列值对应的ID)以及为每一个列值创建其bitmap索引以帮助快速定位哪些行拥有该列值。


基于实时节点的架构


Druid早的架构是基于实时节点(Realtime Node)的。它的特点是有专门的实时节点来负责消费数据。



Druid自身包含以下 4 类节点。



同时,集群还包含以下三类外部依赖。



从数据流转的角度来看,数据从架构图的左侧进入系统,分为实时流数据与批量数据。实时流数据会被实时节点消费,然后实时节点将生成的 Segment 数据文件上传到数据文件存储库;而批量数据经过 Druid 集群消费后会被直接上传到数据文件存储库。同时,查询节点会响应外部的查询请求,并将分别从实时节点与历史节点查询到的结果合并后返回。


基于Indexing Service的架构


在基于Indexing Service的架构中,实时节点被废弃掉了,转而代之的Overlord节点和MiddleManager节点。其中,Overlord节点作为索引服务的主节点,对外负责接收任务请求,对内负责将任务分解并下发到从节点即MiddleManager节点上。而MiddleManager节点就是索引服务的工作节点,负责接收统治节点分配的任务,然后启动相关苦工(Peon)即独立的 JVM 来完成具体的任务。这样的架构实际与 Hadoop Yarn 很像。


较之基于实时节点的架构,基于Indexing Service的架构有不少优点:除了对数据能够用 pull 的方式外,还支持 push 的方式;不同于手工编写数据消费配置文件的方式,可以通过 API 的编程方式来灵活定义任务配置;可以更灵活地管理与使用系统资源;可以完成 Segment 副本数量的控制;能够灵活完成跟 Segment 数据文件相关的所有操作,如合并、删除 Segment 数据文件等。



查询


Druid的默认提供了HTTP REST 风格的查询接口。一个典型的 curl 命令如下: curl -X POST ':/druid/v2/?pretty' -H 'Content-Type:application /json' -d @ 。


其中,queryablehost:port 为查询节点的 IP 地址和端口;queryjson_ le为POST到查询节点的查询请求。


为了便于用户进行灵活的OLAP分析,Druid提供了丰富的查询接口,比如过滤器、聚合器和后置聚合器等。由于这部分内容比较好理解,而且Druid官网上有详细的介绍,因此本文就不再过多说明,这里仅聚一个实际的查询例子如下:


{

    "queryType": "timeseries",

    "dataSource": "visitor_statistics",

    "granularity": "all",

    "filter": {

        "type": "and",

        "fields": [

            {

                "type": "selector",

                "dimension": "host",

                "value": "www.mejia.wang"

            },

            {


        }

    ]

},

"aggregations": [

    {

        "type": "longSum",

        "name": "pv",

        "fieldName": "counbt"

    },

    {


    },

    {

        "type": "hyperUnique",

        "name": "new_visitor_count",

        "fieldName": "new_visit_count"

    },

    {


    }

],

"postAggregations": [

    {

        "type": "arithmetic",

        "name": "new_visitor_rate",

        "fn": "/",

        "fields": [

            {

                "type": "hyperUniqueCardinality",

                "fieldName": "new_visitor_count"

            },

            {

                "fieldName": "visitor_count"

            }

        ]

    },

    {

        "type": "arithmetic",

        "name": "click_rate",

        "fn": "/",

        "fields": [

            {

                "type": "hyperUniqueCardinality",

                "fieldName": "click_visitor_count"

            },

            {

                "type": "hyperUnique",

                "name": "click_visitor_count",

                "fieldName": "click_visit_count""type": "hyperUniqueCardinality",

                "type": "hyperUniqueCardinality",

                "fieldName": "visitor_count"

            }

        ]

    }

],

"intervals": [

    "2016-08-07T00:00:00+08:00/2016-09-05T23:59:59+08:00"

]

}


返回结果可能如下:


[

    {

        "timestamp": "2016-08-27T16:00:00.000Z",

        "result": {

            "pv": 30.000000061295435,

            "visit_count": 5.006113467958146,

            "new_visitor_count": 0,

            "click_visitor_count": 5.006113467958146,

            "new_visitor_rate": 0,

            "click_rate": 1,


    }

}

]


丰富的辅助功能


Druid除了基本的核心数据消费和查询功能外,还提供了丰富的辅助功能,以帮助用户更好地基于Druid完成数据处理工作。本文简单列举几个:



{"timestamp": "2011-01-12T00:00:00.000Z", "tags": ["t1","t2","t3"]} #row1 {"timestamp": "2011-01-13T00:00:00.000Z", "tags": ["t3","t4","t5"]} #row2


本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

回到顶部
嘿,我来帮您!