Druid 笔记一

1 Druid概述  

1.1 什么是Druid

数据分析的基础架构可以分为以下几类:

  • 使用Hadoop/Spark进行分析
  • Hadoop/Spark的结果导入 RDBMS 中提供数据分析
  • 将结果保存到容量更大的 NoSQL 数据库中,解决数据分析的存储瓶颈,例如:HBase
  • 将数据源进行流式处理,对接流式计算框架(如StormSparkFlink),结果保存到 RDBMSNoSQL中
  • 将数据源进行流式处理,对接分析数据库,例如:Druid
Druid 是一个开源的数据分析引擎工具,为实时和历史数据的次秒级(多于一秒)查询设计。主要应用于对数据的OLAP查询, Druid 提供低延迟(实时)的数据摄取、灵活的数据探索、快速的数据聚合。现有的 Druid 部署已支持扩展到数万亿时间和 PB 级数据

1.2 与其他OLAP技术对比

SparkSQL / Impala / ClickHouse ,支持海量数据,灵活性强,但对响应时间是没有保证的。当数据量和计算复杂度增加后,响应时间会变慢,从秒级到分钟级,甚至小时级都有可能。
搜索引擎架构的系统( Elasticsearch 等),在入库时将数据转换为倒排索引。牺牲了灵活性换取很好的性能,在搜索类查询上能做到亚秒级响应,但是对于扫描聚合为主的查询,随着处理数据量的增加,响应时间也会退化到分钟级。
Druid / Kylin ,则在入库时对数据进行预聚合,进一步牺牲灵活性换取性能,以实现对超大数据集的秒级响应。
  • Kylin 利用 Hadoop/HBase 做计算和存储,使用 SQL 查询,提供 JDBC/ODBC 驱动与常见 BI 工具集成
  • Druid 有自己独立的分布式集群,能够实时摄入数据,有自己的查询接口(与BI兼容性较弱),通常多用于实时要求高的场景
目前没有一个 OLAP 分析引擎能在数据量、灵活程度、性能(吞吐 & 并发)做到完美,需要基于自己的业务场景进行取舍和选型。

1.3 技术特点

Apache Druid 是一个开源的、分布式、实时 OLAP 分析工具。 Druid 的核心设计结合了数据仓库、时间序列数据库和搜索系统的思想,适用于多种场景的高性能数据实时分析。Druid 将这三个系统中的每个系统的关键特征合并到其接收层、存储格式、查询层和核心体系结构中。

时间序列数据库主要用于指处理,带时间标签(按照时间的顺序变化)的数据,带时间标签的数据也称为时间序列数据。
时间序列数据主要由电力行业、化工行业等各类型实时监测、检查与分析设备所采集、产生的数据,这些工业数据的典型特点是:产生频率快(每一个监测点一秒钟内可产生多条数据)、严重依赖于采集时间(每一条数据均要求对应唯一的时间)、测点多信息量大(常规的实时监测系统均有成千上万的监测点,监测点每秒钟都产生数据,每天产生几十GB 的数据量)。
1 、主要特点
  • 列式存储 Druid 独立的存储和压缩每一列,只需要读取特定查询所需的内容,这可以支持快速扫描、排名和聚合
  • 流式和批量摄取(Ingestion) 支持 Apache KafkaHDFSAWS S3stream processors 等现成连接器
  • 本地的搜索索引  Druid 为字符串创建倒排索引,以支持快速搜索和排序
  • 灵活的 schema Druid 可以处理变化的 schema 和嵌套数据
  • 基于时间优化 partition  Druid 基于时间智能的对数据进行分区,基于时间的查询比传统数据库要快得多 
  • 支持 SQL  Druid支持本机的 JSON 语言,还支持基于 HTTP 或者 JDBC 的 SQL
  • 水平扩展性  Druid 已经用户生产环境中,每秒接收数百万个事件,保存多年的数据并提供次秒级查询
  • 操作简单  只需要增加或删除服务器即可扩展或缩小规模,Druid 会自动平衡,容错架构通过服务器的故障进行路由

2、集成

Druid 是开源大数据技术的补充,包括 Apache Kafka Apache Hadoop Apache Flink 等,通常位于存储或处理层与最终应用之间,充当查询层或数据分析服务。

3 Ingestion (摄取)
Druid 支持流式传输和批量摄取。 Druid 连接到数据源,包括: Kafka (用于流数据加载),或分布式文件系统,如HDFS(用于批处理数据加载)。
Druid 索引 过程中将数据源中的原始数据转换为支持高效读取的优化格式( Segment ,段)。

4、存储
Druid的数据存储采用列式存储格式。根据列的类型(字符串,数字等),应用不同的压缩和编码方法,根据列类型构建不同类型的索引。
Druid为字符串列构建倒排索引,以进行快速搜索和过滤。Druid可按时间对数据进行智能分区,以实现面向时间的快速查询。
Druid在摄取数据时对数据进行预聚合,节省大量存储空间。

 
5、查询方式
Druid
支持JSON、SQL两种方式查询数据

1.4 应用场景

Druid擅长的部分
  • 对于大部分查询场景可以亚秒级响应
  • 事件流实时写入与批量数据导入兼备
  • 数据写入前预聚合节省存储空间,提升查询效率
  • 水平扩容能力强
  • 社区活跃


是否需要使用Druid

  • 处理时间序列事件
  • 快速的聚合以及探索式分析
  • 近实时分析亚秒级响
  • 存储大量(TB级、PB)可以预先定义若干维度的事件
  • 无单点问题的数据存储

2 Druid 架构与原理

2.1 基础架构

  • Coordinator node 进程管理群集上的数据可用性。从metastore中读取Segment的元数据,并决定哪些Segments需要被加载到集群中。使用ZooKeeper查看已经存在的历史节点,了解集群各个节点负载情况。创建一个ZK的条目告诉历史节点加载、删除、或者移动Segments。主要负责历史节点的数据负载均衡,以及通过规则管理数据的生命周期。协调节点告诉历史节点加载新数据、卸载过期数据、复制数据、 和为了负载均衡移动数据
    Coordinator 是周期性运行的(由 druid.coordinator.period 配置指定,默认执行间隔为 60s);
    Coordinator 需要维护和 ZooKeeper 的连接,以获取集群的信息。Segment 和 Rule 的信息保存在元数据库中,所以也需要维护与元 数据库的连接。
  • Overlord node 进程控制数据提取工作负载的分配。进程监视 MiddleManager 进程,并且是Druid 数据摄入的主节点。负责将提取任务分配给MiddleManagers 并协调 Segement 发布,包括接受、拆解、分配 Task,以及创建 Task 相关的锁,并返回 Task 状态。
  • Historical node 进程存储可查询数据。提供对Segment的数据查询服务。与ZooKeeper通信,上报节点信息,告知ZK自己拥有哪些Segments。从ZooKeeper中获取执行任务。加载生成好的数据文件,以供数据查询。Historical node是整个集群查询性能的核心所在,Historical 会承担绝大部分的 segment 查询
    Historical 进程从 Deep Storage 中下载 Segment,并响应有关这些 Segment 的查询请求(这些请求来自Broker 进程);
     Historical 进程不处理写入请求; 
    Historical 进程采用了无共享架构设计,它知道如何去加载和删除 Segment,以及如何基于 Segment 来响应查询。
    即便 底层的深度存储无法正常工作,Historical 进程还是能针对其已同步的 Segments,正常提供查询服务。
  • MiddleManager node 进程负责提取数据。及时摄入实时数据,生成 Segment 数据文件。
    MiddleManager 进程是执行提交任务的工作节点。MiddleManagers 将任务转发给在不同 JVM 中运行的 Peon 进程。
    MiddleManager、Peon、Task 的对应关系是,每个 Peon 进程一次只能运行一个Task 任务,但一个 MiddleManager 却可以管理多个 Peon 进程。
  • Broker node 进程处理来自外部客户端的查询。负责将查询请求分发到历史节点和实时节点,并聚合这些节点返回的查询结果数据。Broker节点通过zooeeper知道Segment都存放在哪些节点上。接收客户端查询请求,并将这些查询转发给 Historicals MiddleManagers。当 Brokers 从这些子查询中收到结果时,它们会合并这些结果并将它们返回给调用者。
    Broker节点负责转发Client查询请求的; Broker通过zookeeper能够知道哪个Segment在哪些节点上,
    将查询转发给相应节点; 所有节点返回数据后,Broker会将所有节点的数据进行合并,然后返回给Client;
  • Router 进程是可选的进程,可以将请求路由到BrokerCoordinatorOverlords。
    Router 进程可以在 Brokers、Overlords 和 Coordinators 进程之上,提供一层统一的 API网关。
    Router 进程是 可选的,如果集群数据规模已经达到了 TB级别,需要考虑启用(druid.router.managementProxy.enabled=true)。 
    一旦集群规模达到一定的数量级,那么发生故障的概率就会变得不容忽视,而 Router 支持将请求只发送给健康的节点,避免 请求失败。
    同时,查询的响应时间和资源消耗,也会随着数据量的增长而变高,而 Router 支持设置查询的优先级和负载均衡 策略,避免了大查询造成的队列堆积或查询热点等问题
根据线程的服务类型分为:
  • MasterCoordinator & Overload 进程,管理数据可用性和数据摄取
  • DataHistorical & MiddleManager,执行提取工作负载并存储所有可查询数据
  • QueryBroker & Router,处理来自外部客户端的查询

2.2 外部依赖

  • Deep Storage:深度存储,例如HDFS或者S3。不是用来存储查询数据的而是作为数据的备份或者进程间数据交换。存放生成的 Segment 数据文件,并供历史服务器下载, 对于单节点集群可以是本地磁盘,而对于分布式集群一般是 HDFS。
    Druid使用deep storage来做数据的备份,也作为在Druid进程之间在后台传输数据的一种方式。 
    当响应查询时,Historical首先从本地磁盘读取预取的段,这也意味着需要在deep storage和加载的数据的Historical 中拥有足够的磁盘空间。
  • Metadata Storage:元数据存储,可以用RDBMS。存储 Druid 集群的元数据信息,如 Segment 的相关信息,一般使用 MySQL
  • ZooKeeper:服务发现、leader选举、服务协调。为 Druid 集群提供以执行协调服务。如内部服务的监控,协调和领导者选举
    Coordinator 节点的 Leader 选举 
    Historical 节点发布 Segment 的协议 
    Coordinator 和 Historical 之间 load / drop Segment 的协议 
    Overlord 节点的 Leader 选举 
    Overlord 和 MiddleManager 之间的 Task 管理

    架构演进

Apache Druid 初始版本架构图 ~ 0.6.0 2012~2013

0.7.0 ~ 0.12.0 2013~2018
Apache Druid 旧架构图 —— 数据流转

Apache Druid 旧架构图 —— 集群管理

0.13.0 ~ 当前版本( 2018~now

Lambda 架构

从大的架构上看, Druid 是一个 Lambda 架构。
Lambda 架构是由 Storm 的作者 Nathan Marz 提出的一个实时大数据处理框架。 Lambda 架构设计是为了在处理大规模数据时,同时发挥流处理和批处理的优势:
  • 通过批处理提供全面、准确的数据
  • 通过流处理提供低延迟的数据
从而达到平衡延迟、吞吐量和容错性的目的, 为了满足下游的即席查询,批处理和流处理的结果会进行合并
Lambda 架构包含三层, Batch Layer Speed Layer Serving Layer
  • Batch Layer:批处理层。对离线的历史数据进行预计算,为了下游能够快速查询想要的结果。由于批处理基于完整的历史数据集,准确性可以得到保证。批处理层可以用 HadoopSpark Flink 等框架计算
  • Speed Layer:加速处理层。处理实时的增量数据,这一层重点在于低延迟。加速层的数据不如批处理层那样完整和准确,但是可以填补批处理高延迟导致的数据空白。加速层可以用 StormSpark streaming Flink 等框架计算
  • Serving Layer:合并层。将历史数据、实时数据合并在一起,输出到数据库或者其他介质,供下游分析

流式数据的链路为:
Row data Kafka Streaming processor (Optional, 实时 ETL) Kafka Optional Druid Application / User
批处理数据的链路为:
Raw data Kafka Optional HDFS ETL process Optional Druid Application / User

3.数据存储

  • Druid中的数据存储在被称为DataSource中,DataSource类似RDBMS中的 Table
  • 每个DataSource按照时间划分,每个时间范围称为一个Chunk(比如按天分区,则一个chunk为一天)
  • Chunk中数据被分为一个或多个Segment  Segment是数据实际存储结构,DatasourceChunk只是一个逻辑概念
  • Segment是按照时间组织成的Chunk,所以在按照时间查询数据时,效率非常高
  • 每个Segment都是一个单独的文件,通常包含几百万行数据

数据分区:
  • Druid处理的是事件数据,每条数据都会带有一个时间戳,可以使用时间进行分区
  • 上图指定了分区粒度为为天,那么每天的数据都会被单独存储和查询
Segment 内部存储结构
  • Druid采用列式存储,每列数据都是在独立的结构中存储
  • Segment中的数据类型主要分为三种
    1. 时间戳。每一行数据,都必须有一个
    timestampDruid一定会基于时间戳来分片
    2.维度列。用来过滤
    filter或者组合groupby的列,通常是stringfloatdoubleint类型
    3.指标列。用来进行聚合计算的列,指定的聚合函数
    sumaverage

MiddleManager 节点接受到 ingestion 的任务之后,开始创建 Segment
  • 转换成列存储格式
  • bitmap来建立索引(对所有的dimension列建立索引)
  • 使用各种压缩算法:
    1. 所有的列使用
    LZ4压缩
    2.所有的字符串列采用字典编码
    /标识以达到最小化存储
    3.对位图索引使用位图压缩
Segment 创建完成之后, Segment文件就是不可更改的,被写入到深度存储 (目的是为了防止 MiddleManager 节点宕机后,Segment 的丢失)。 然后 Segment 会加载到 Historical 节点, Historical节点可以直接加载到内存中。
同时, metadata store 也会记录下这个新创建的Segment的信息 ,如结构,尺寸,深度存储的位置等等。 Coordinator节点需要这些元数据来协调数据的查找。

4.索引服务

  • 索引服务:数据导入并创建 segments 数据文件的服务
  • 索引服务是一个高可用的分布式服务,采用主从结构作为架构模式,索引服务由三大组件构成
    1.overlord 作为主节点
    2.middlemanager是从节点
    3.peon
    用于运行一个task

索引服务架构图如下图所示:

索引服务由三部分组件组成:
  • Overlord组件  负责创建task、分发taskmiddlemanager上运行,为task创建锁以及跟踪task运行状态并反馈给用户
  • MiddleManager组件  作为从节点,负责接收主节点分配的任务,然后为每个task启动一个独立的JVM进程来完成具体的任务
  • Peon(劳工)组件 由middlemanager启动的一个进程用于运行一个task任务

 索引服务架构与 Yarn 的架构类似:

  • Overlaod => ResourceManager,负责集群资源管理和任务分配
  • MiddleManager => NodeManager,负责接受任务和管理本节点的资源
  • Peon => Container,执行节点上具体的任务
Task 类型有很多,包括:
  • index hadoop taskHadoop索引任务,利用Hadoop集群执行MapReduce任务以完成segment数据文件的创建,适合体量比较大的segments数据文件的创建任务
  • index kafka task:用于Kafka数据的实时摄入,通过Kafka索引服务可以在Overlord上配置一个KafkaSupervisor,通过管理Kafka索引任务的创建和生命周期来完成 Kafka 数据的摄取
  • merge task:合并索引任务,将多个segments数据文件按照指定的聚合方法合并为一个segments数据文件
  • kill task : 销毁索引任务,将执行时间范围内的数据从Druid集群的深度存储中删除

5.索引及压缩机制

Druid 的查询时延低性能好的主要是因为采用了五个技术点:
  • 数据预聚合
  • 列式存储、数据压缩
  • Bitmap 索引
  • mmap(内存文件映射方式)
  • 查询结果的中间缓存

1、数据预聚合

  • Druid通过一个roll-up的处理,将原始数据在注入的时候就进行汇总处理
  • Roll-up可以压缩我们需要保存的数据量
  • Druid会把选定的相同维度的数据进行聚合操作,可减少存储的大小
  • Druid可以通过 queryGranularity 来控制注入数据的粒度。 最小的queryGranularity millisecond(毫秒级)
Roll-up 聚合前:

Roll-up 聚合后:

2、位图索引

Druid 在摄入的数据示例:

  • 第一列为时间,AppkeyArea都是维度列,Value为指标列
  • Druid会在导入阶段自动对数据进行Rollup,将维度相同组合的数据进行聚合处理
  • 数据聚合的粒度根据业务需要确定
按天聚合后的数据如下:

Druid 通过建立位图索引,实现快速数据查找。
Bitmap 索引主要为了加速查询时有条件过滤的场景。 Druid 在生成索引文件的时候,对每个列的每个取值生成对应的 Bitmap 集合。如下图所示:

索引位图可以看作是 HashMap<String, Bitmap>
  • key就是维度的取值
  • value就是该表中对应的行是否有该维度的值

SQL查询为例:

1boolean条件查询

select sum(value) 
from tab1 
where time='2020-10-01' 
and appkey in ('appkey1', 'appkey2') 
and area='北京'
执行过程分析:
  • 根据时间段定位到segment
  • Appkey in ('appkey1', 'appkey2') and area='北京' 查到各自的bitmap
    1. (appkey1 or appkey2) and 北京
    2.(110000 or 001100) and 101010 = 111100 and 101010 = 101000
    3.符合条件的列为:第
    1 & 3行,这几行 sum(value) 的和为 40
2 group by 查询
select area, sum(value) 
from tab1 
where time='2020-10-01' 
and appkey in ('appkey1', 'appkey2') 
group by area
该查询与上面的查询不同之处在于将符合条件的列
  • appkey1 or appkey2
  • 110000 or 001100 = 111100
  • 将第1行 到 第4行取出来
  • 在内存中做分组聚合。结果为:北京:40、深圳:60
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值