在本文中,我们将对Apache Druid框架有一个完整的概述,从什么是timeseries(时间序列)开始,我们如何处理此类数据,以及对其体系结构的描述。最后,我们将看到如何在平台内接收和查询数据。
时间序列
时间序列是按时间顺序排列的数据点序列。
这些离散点通常被存储和分析,以便做出预测或发现行为模式。在常见的大数据体系结构中,标准方法是收集来自各种来源的数据(用户数据、应用程序数据、web分析、bi度量等),将所有数据发送到ETL流处理器,并在实时仪表板中可视化信息。
为了使流程更具分析性,并且能够更快地响应timeseries查询,我们的体系结构可以分为两个不同的管道:
- 一个专用于用户和应用程序数据,具有如上所述的标准结构;
- 另一种方法是,对于收集的其余数据,在ETL步骤之后,将数据存储到分析数据库中,然后再将其连接到实时仪表板。
作为我们的分析数据库,我们将需要一些能够实时接收数据、具有低延迟查询和高正常运行时间的东西……apachedruid是否是一个完美的选择?
Apache Druid简介
Druid是一个用于事件驱动数据的高性能分析数据存储,用Java编写,于2011年诞生,并于2015年2月转移到Apache许可证。它有很多特点,最引人注目的是:
- 可扩展性,得益于自我修复的架构
- 典型的<1s到4–5s查询延迟
- 列数据集上的灵活表模式
- 基于时间的分区和查询
- 原生JSON+标准SQL查询
- 快速数据预聚合
数据可以通过两种数据源存储在Druid中:批处理(Native、Hadoop等)和流处理(Kafka、Kinesis、tanquity等)。在这两种情况下,数据的存储方式相当于关系数据库中的表,在接收过程中使用时间分区,将块构建成分区段。
在摄取之后,一个段成为一个不可变的列压缩文件。这个不可变的文件被持久保存在一个深度存储(例如S3或HDFS)中,即使在所有Druid服务器发生故障后也可以恢复。存储利用地图和压缩位图来达到高压缩率。
在Apache Druid中,有三种类型的列:
- 时间戳→ 用于分区和排序
- 尺寸→ 可以通过过滤器查询的字段
- 公制→ 可选字段,表示从其他字段聚合的数据(例如另一个字段中的字符总数)
查询可以通过两种不同的方式发送到Druid,而不会导致性能损失:原生druidjson或DruidSQL。Druid针对单个事实数据源上的查询进行了优化,并且只针对单个简单的查询时查找表进行联接。
进一步的连接并不完全受支持,而且在查询响应时间方面也不是最优的。
让我们深入看看引擎盖下面。
框架体系结构
Druid架构可以分为三个不同的层次:
- 数据服务器
- 主服务器
- 查询服务器
每个Druid层都致力于一个非常具体的任务。
数据服务器层
在这一层中,数据被摄取、存储和检索。
数据通过MiddleManagers进入框架,MiddleManagers是通过处理任务和创建新段来处理摄取的组件。他们负责如何对数据进行索引、预聚合、拆分成段并发布到深度存储中。
深度存储负责持久化接收的所有数据,并处理进程之间的存储备份和可用性。这个组件是可插入的,因此用户可以选择最合适的存储。
属于该子类别的其他组件包括Zookeeper(另一个用于内部服务发现、协调和领导选举的Apache项目)和元数据存储(由关系数据库支持,如MySQL或PostgreSQL),其中包含所有组件以前收集的所有可用元数据。
这一层的最后一个实体是历史实体:它们负责处理查询处理,方法是将数据段从深存储器提取到本地磁盘,并在查询请求时为它们提供服务。如果在缓存中找不到任何信息,则从Zookeeper检索新段的元数据(位置和压缩),并在该位置处理数据。摄取数据队列中的每个新段条目都会触发历史记录。
主服务器层
该层使用霸主管理数据可用性和摄取,这些组件通过MiddleManager
进程平衡数据,分配摄取任务并协调段可用性。
另一方面,协调器是在历史进程之间平衡数据的组件,在需要加载段时通知它们,删除过时的段并管理段复制。
查询服务器层
该层负责处理来自外部客户机的查询并提供结果。它使用称为代理的组件,这些组件接收来自客户端的查询,确定哪些历史节点和MiddleManager节点正在为这些段提供服务,将主查询拆分并重写为子查询,并将所有内容发送到这些进程中的每一个。最后,经纪人收集并合并要提供给客户的结果。
在介绍架构之后,我们将看到实际的Druid任务是如何执行的。
摄入流
定义从我们的数据源摄取数据的主要阶段有两个:
- 索引
- 正在获取
在索引阶段,首先从源(1)收集数据,然后对它们进行索引和预聚合(2),以便创建新的段并将其发布(3)到深度存储器中。
在获取阶段,由于协调器定期侦听新发布的段的元数据存储(4),当其中一个发现已发布和使用但不可用的段时,它会选择一个历史进程将该段加载到内存中,并指示该历史进程这样做(5)。最后,历史记录执行其任务并开始服务数据(6)。
查询流程
当用户向Druid提交查询时会发生什么?
下面将在称为查询阶段的单个阶段中描述该过程。
当客户机发出一个由代理(7)管理的请求时,这一切就开始了,代理将识别服务于那些相应段(8)的进程。然后,该查询将被拆分、重写并发送(9)给Historicals
和MiddleManagers
,以便在整个集群(10)上执行。
历史记录从深层存储器中获取数据。但是,对于实时数据,查询也可以发送到MiddleManagers
:有些数据可能还不能在DeepStorage
中使用,但只作为仍在等待写入底层文件系统的段存在。
最后,查询结果由代理收集并合并在一起,并显示给客户机(11)。
关键的一点是,在接收阶段,为了预聚合和索引数据而花费的时间成本在查询时恢复回来。这使得用户能够以平均亚秒的查询响应时间获得高速结果。
结论
在本文中,我们分析了:
- Apache Druid框架的主要特性
- 哪些组件定义了它的体系结构及其用途
- 定义接收和查询阶段的主要步骤
Apache Druid的结构并不是真正的轻量级的,因为它涉及到大量的组件。不过,这允许适当地横向扩展体系结构,只需增加节点的数量(中间管理器、历史记录等)。此外,它在批处理和实时处理数据方面提供了高性能。
多亏了开源代码,在Druid上使用或开发的社区正在增长,例如,可以找到或定义连接器,以便在需要的体系结构中包含框架。
该项目目前已被许多成功的公司应用于生产中,这是因为它具有良好的性能和适合的各种各样的用例。
除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/1888.html
暂无评论