Druid是什么
Druid是是个内存数据库也是一个时序数据库,是一个分布式内存实时分析系统,用于解决如何在大规模数据集下进行快速的、交互式的查询和分析的问题。数据可以实时摄入也可以批量摄入,进入到Druid后立即可查,同时数据是几乎是不可变。
Druid不适合存储明细表,Druid是基于时间、维度列预聚合的,明细表不会发挥出Druid的预聚合特性。明细表建议使用clickhouse。
优点:
-
列式存储,支持的数据规模大(本地存储+DeepStorage–HDFS),以segment为单位,每个segment内列式存储,并可以对每列建立索引。
-
采用LSM-Tree结构,有极高的写入性能, 同时实现了实时数据在亚秒级的可视化
-
列式存储, 倒排索引,位图索引,预聚合(roll-up)等机制, 可在亚秒级完成对数据的过滤, 聚合以及多维分析
缺点: -
易用性较差,不支持join,不支持更新,sql支持很弱(有些插件类似于pinot的PQL语言),只能JSON格式查询;
-
对于去重操作不能精准去重(支持小数据集的精确去重,效果很差,一般采用hll算法进行模糊去重)
-
需要流处理引擎将数据join为宽表, 维护复杂, 对内存要求较高
Druid基本概念
Druid数据格式
- 时间列(Timesatmp):表明每行数据的时间值,默认使用UTC时间格式并且精确到毫秒级别。这个列是数据聚合与范围查询的重要维度。
- 维度列(Dimension):维度来自于OLAP的概念,用来标识数据行的各个类别信息。
- 指标列(Metrics):指标对应于OLAP概念中的Fact,是用于计算和聚合的列。指标列通常是一些数字,计算操作通常包括Count,Sum,Mean等。
预聚合:druid对指定时间粒度内的值按维度列进行预聚合(group by 维度列)
这种预聚合的方式可以很显著的减少数据的存储(可减少100倍)。 Druid也是通过这种方式来减少数据的存储。 这种减少存储的方式也会带来副作用,比如我们没有办法再查询到每条数据具体的明细。换句话说,数据聚合的粒度是我们能查询数据的最小粒度。
数据分片
Segment是数据的实际物理存储格式。Druid正是通过Segment实现对数据横向切割操作。从数据时间分布的角度来看,通过参数segmentGranularity的设置。Druid将不同的时间范围内的数据存储在不同的segment块中,这便是所谓的横向切割。这样访问Druid的数据仅需要访问对应时间的segment数据块,而不需要进行全表的数据范围查询。
同时在segment中也面向列进行数据压缩存储,这便是所谓的数据纵向切割。而且在Segment中使用了Bitmap进行了数据访问进行了优化。
二级分片
支持两种类型的分区策略:“散列”、“单维度”。在大多数情况下,建议使用散列分区,可以提高索引性能和创造大小更均匀的数据段。基于哈希散列首先选择第一级分片的segments,然后根据segments每一行的所有维度的hash来划分。
"partitionsSpec": {
"type”: “hashed",
"targetPartitionSize: 5000000
}
numShards:可以直接指定shard个数。当配置这个参数时,还可以配置partitionDimensions来指定维度,而不用全部维度。
shard大小推荐
根据官方文档,shard大小推荐为300MB-700MB,需要调整两级分片的参数segmentGranularity和partitioningSpec。shard相当于是druid数据最小存储单位,分得太大的话,可能在各个历史节点分散不开。分得合适的话,查询的时候在历史节点比较分散,可以充分利用每个历史节点的cpu。
Druid架构
Druid包含以下四个节点:
- 实时节点(Realtime ):即时摄入实时数据,以及生成Segment数据文件
实时节点负责消费实时数据,实时数据首先会被直接加载进实时节点内存中的堆结构缓存区,当条件满足时,缓存区的数据会被冲写到硬盘上形成一个数据块(Segment Split),同时实时节点又会立即将新生成的数据库加载到内存的非堆区,因此无论是堆结构缓存区还是非堆区里的数据都能被查询节点(Broker Node)查询。旧数据会被从Realtime节点转存至Historical节点。 - 历史节点(Historical Node):加载已经生成好的文件,以供数据查询。负责加载Druid中非实时窗口内且满足加载规则的所有历史数据的Segment。每一个Historical Node只与Zookeeper保持同步,不与其他类型节点或者其他Historical Node进行通信。
- 查询节点(Broker Node):对外提供数据查询服务,并同时从实时节点和历史节点查询数据,合并后返回给调用方。
Broker节点会感知Zookeeper上保存的集群发布的Segment的元信息(每个Segment的存储节点),Broker节点还会为每个Zookeeper上的DataSource创建一个timeLine,timeLine按时间顺序描述每个Segment存放位置。Broker节点根据这些信息查询满足条件的存储节点。
Broker节点会缓存历史节点上查询的不可变信息,不会缓存实时节点上查询的可变信息。 - 协调节点(Coordinator Node):负责历史节点的数据负载均衡,以及通过规则(Rule)管理数据的生命周期
Druid依赖组件
- 元数据库(Metastore):存储Druid集群的原数据信息,比如Segment的相关信息,一般用MySql或PostgreSQL
- 分布式协调服务(Coordination):为Druid集群提供一致性协调服务的组件,通常为Zookeeper
- 数据文件存储系统(DeepStorage):存放生成的Segment文件,并供历史节点下载。对于单节点集群可以是本地磁盘,而对于分布式集群一般是HDFS或NFS
历史节点在启动的时候 :
- 会去检查自己本地缓存中已经存在的Segment数据文件
- 从DeepStorege中下载属于自己但是目前不在自己本地磁盘上的Segment数据文件
无论何种查询,历史节点会首先将相关Segment数据文件从磁盘加载到内存,然后在提供查询
优缺点
分布式内存实时分析系统,用于解决如何在大规模数据集下进行快速的、交互式的查询和分析的问题
优点:
列式存储,支持的数据规模大(本地存储+DeepStorage--HDFS)
采用LSM-Tree结构,有极高的写入性能, 同时实现了实时数据在亚秒级的可视化
列式存储, 倒排索引,位图索引,预聚合(roll-up)等机制, 可在亚秒级完成对数据的过滤, 聚合以及多维分析
缺点:
易用性较差,不支持join,不支持更新,sql支持很弱(有些插件类似于pinot的PQL语言),只能JSON格式查询;
对于去重操作不能精准去重。
需要流处理引擎将数据join为宽表, 维护复杂, 对内存要求较高