Apache Druid

Druid翻译零:概念

2017-02-05  本文已影响761人  Sisyphus秋居拾遗

Druid是一个专门针对事件数据的OLAP查询而设计的开源数据存储系统。此页面旨在为读者介绍关于Druid存储数据的高级概述,以及Druid集群的架构。

数据

我们从一个在线广告的示例数据集开始讨论:

timestamp             publisher          advertiser  gender  country  click  price
2011-01-01T01:01:35Z  bieberfever.com    google.com  Male    USA      0      0.65
2011-01-01T01:03:63Z  bieberfever.com    google.com  Male    USA      0      0.62
2011-01-01T01:04:51Z  bieberfever.com    google.com  Male    USA      1      0.45
2011-01-01T01:00:00Z  ultratrimfast.com  google.com  Female  UK       0      0.87
2011-01-01T02:00:00Z  ultratrimfast.com  google.com  Female  UK       0      0.99
2011-01-01T02:00:00Z  ultratrimfast.com  google.com  Female  UK       1      1.53

熟悉OLAP的同学应该对这些概念肯定不会陌生,Druid也把数据集分为三个部分:

Roll-up

在海量数据处理中,一般对于单条的细分数据并不感兴趣,因为存在数万亿计这样的事件。然而这类数据的统计汇总是很有用的,Druid通过roll-up过程的处理,使数据在摄取加载阶段就做了汇总处理。Roll-up(汇总)是在维度过滤之前就做的第一级聚合操作。相等于如下伪代码:

GROUP BY timestamp, publisher, advertiser, gender, country
  :: impressions = COUNT(1),  clicks = SUM(click),  revenue = SUM(price)

原始数据压缩聚合之后就是这个样子:

 timestamp             publisher          advertiser  gender country impressions clicks revenue
 2011-01-01T01:00:00Z  ultratrimfast.com  google.com  Male   USA     1800        25     15.70
 2011-01-01T01:00:00Z  bieberfever.com    google.com  Male   USA     2912        42     29.18
 2011-01-01T02:00:00Z  ultratrimfast.com  google.com  Male   UK      1953        17     17.31
 2011-01-01T02:00:00Z  bieberfever.com    google.com  Male   UK      3194        170    34.01

可以看到,通过roll-up汇总数据后可以大大减少需要存储的数据量(高达100倍)。Druid在接收数据的时候汇总数据,以最小化需要存储的原始数据量。但是这种存储减少是有代价的,当我们roll up数据后,就没办法再查询详细数据了。换句话说roll-up后的粒度就是你能够探索数据的最小粒度,事件被分配到这个粒度。因此,Druid摄取规范将此粒度定义为数据的queryGranularity, 支持的最低queryGranularity是毫秒。

Sharding the Data

Druid的数据分片称为 segments,druid总是最先通过时间来分片,上面例子中我们聚合后的数据,可以按小时分为俩分片:
Segment sampleData_2011-01-01T01:00:00:00Z_2011-01-01T02:00:00:00Z_v1_0包含

 2011-01-01T01:00:00Z  ultratrimfast.com  google.com  Male   USA     1800        25     15.70
 2011-01-01T01:00:00Z  bieberfever.com    google.com  Male   USA     2912        42     29.18

Segment sampleData_2011-01-01T02:00:00:00Z_2011-01-01T03:00:00:00Z_v1_0包含

 2011-01-01T02:00:00Z  ultratrimfast.com  google.com  Male   UK      1953        17     17.31
 2011-01-01T02:00:00Z  bieberfever.com    google.com  Male   UK      3194        170    34.01

segments是一个包含数据的独立容器,内部数据以时间分割。segments为聚合的列做索引,数据依赖索引,按列方式存储。 所以druid得查询就转为了如何扫描segments了。
segment 由datasource(数据源)、interval(间隔)、version(版本号)和一个可选的分区号唯一的确定。 例如上面例子中,我们的segment的名字就是这种格式dataSource_interval_version_partitionNumber。

Indexing the Data

Druid能够取得这样的查询速度,主要取决于数据的存储方式。借鉴google等搜索引擎的思路,Druid生成不可变的数据快照,存储在针对分析查询高度优化的数据结构中。
Druid是列式存储也就意味着每一个列都是单独存储的。Druid查询时只会使用到与查询相关的列,而且Druid很好的支持了在查询时只扫描其需要的。不同的列可以采用不同的压缩方法,也能够建立与它们相关的不同索引。
Druid在每一个分片级别(segment)建立索引。

Loading the Data

Druid有实时和批量两种方式进行数据摄取。Druid中实时数据摄取方式是尽力而为。Druid暂时实时摄取暂时无法支持正好一次(Exactly once),当然在后续版本计划中会尽量去支持。通过批量创建能够准确映射到摄取数据的段,批量摄取提供了正好一次的保证。使用Druid的通用方式是用实时管道获取实时数据,用批量管道处理副本数据。

Querying the Data

Druid的本地查询语言是JSON通过HTTP,虽然社区在众多的语言中提供了查询库,包括SQL查询贡献库。
Druid设计用于单表操作,目前不支持join操作。因为加载到Druid中的数据需要规范化,许多产品准备在数据ETL(Extract-Transform-Load)阶段进行join。

The Druid Cluster

Druid集群是由不同类型节点组成的,每个节点各司其职:

外部依赖

Druid对集群操作有几个外部依赖关系。

高可用性

Druid设计避免了单点故障。不同类型的节点故障并不会影响其他类型节点的服务。为了运行高可用的Druid集群,需要每个节点类型至少2个节点。

全面架构

Druid论文

原文链接:http://druid.io/docs/0.9.2/design/

上一篇 下一篇

猜你喜欢

热点阅读