Apache Druid 集群搭建及使用【超全面】

一、Druid 简介

1.1 大数据分析平台架构分类

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

  • 使用Hadoop/Spark 进行分析
  • 将Hadoop/Spark 的结果导入 RDBMS 中提供数据分析;补充说明:RDBMS一般指关系数据库管理系统
  • 将结果注入到容量更大的NoSQL中,解决数据分析的存储瓶颈,例如:HBase
  • 将数据源进行流式处理,对接流式计算框架,例如:Flink、Spark Streaming,结果保存到RDBMS、NoSQL中
  • 将数据源进行流式处理,对接分析数据库,例如:Druid

二、为什么会有Druid?

2.1 基于Hadoop 大数据平台的问题 

基于Hadoop 的大数据平台,有如下一些问题:

  • 无法保障查询性能
    • 对于Hadoop 使用的MapReduce 批处理框架,数据何时能够查询没有性能保证
  • 随机IO 问题 
    • HDFS 以集群硬盘作为存储资源池的分布式文件系统
    • 在海量数据的处理过程中,会引起大量的读写操作,随机IO 是高并发场景下的性能瓶颈
  • 数据可视化问题 
    • HDFS 对于数据分析以及数据的即席查询,HDFS 并不是最优的选择

传统的Hadoop 大数据处理架构更倾向于一种 “后台批处理的数据仓库系统”,其作为海量历史数据保存、冷数据分析,确实是一个优秀的通用解决方案,但

  • 无法保证高并发环境下海量数据的查询分析性能
  • 无法实现海量实时数据的查询分析与可视化

2.2 Druid 的诞生

  •  Druid 是由一个名为 MetaMarket 的公司开发的
  • 2011年,MetaMarket 开始研发自己的“轮子” Druid,将Druid 定义为“开源、分布式、面向列式存储的实时分析数据存储系统”
  • 要解决的“痛点”是
    • 在高并发环境下,保证海量数据查询分析性能
    • 同时提供海量实时数据的查询、分析与可视化功能

2.3 Druid 是什么

官方文档链接:https://docs.imply.io/latest/quickstart/

Druid 是面向海量数据的、用于实时查询与分析的OLAP 存储系统。Druid 的四大关键特性如下:

  • 亚秒级的OLAP 查询分析
    • 采用了列式存储、倒排索引、位图索引等关键技术
  • 在亚秒级别内完成海量数据的过滤、聚合以及多维分析等操作
  • 实时流数据分析
    • 传统分析型数据库采用的批量导入数据,进行分析的方式
    • Druid 提供了实时流数据分析,以及高效实时写入
  • 实时数据在亚秒级内的可视化
  • 丰富的数据分析功能
    • Druid 提供了友好的可视化界面
  • SQL 查询语言
    • REST 查询接口
  • 高可用性与高可拓展性
    • Druid 工作节点功能单一,不相互依赖
    • Druid 集群在管理、容错、灾备、扩容都很容易

阿里巴巴也曾创建过一个开源项目叫Druid (简称阿里 Druid),它是一个数据库连接池项目。阿里Druid 和我们要讨论的Druid 没有任何关系,它们解决完全不同的问题 。


2.4 Druid 典型应用架构


2.5 国内哪些公司在使用Druid

  • 腾讯
    • 腾讯企业采用Druid 用于分析大量的用户行为,帮助提升客户价值
  • 阿里巴巴
    • 阿里搜索组使用Druid 的实时分析功能用于获取用户交互行为
  • 新浪微博
    • 新浪广告团队使用Druid 构建数据洞察系统的实时分析部分,每天处理数十亿的消息
  • 小米
    • Druid 用于小米统计的后台数据收集和分析
    • 也用于广告平台的数据分析
  • 滴滴打车
    • Druid 是滴滴实时大数据处理的核心模块,用于滴滴实时监控系统,支持数百个关键业务指标
    • 通过Druid,滴滴能够快速得到各种实时的数据洞察
  • 优酷土豆
    • Druid 用于其广告的数据处理和分析

2.6 Druid 对比其他OLAP

2.6.1 Druid vs. ElasticSearch

  • Druid 在导入过程会对原始数据进行Rollup聚合】,而Es 会保存原始数据
  • Druid 专注于OLAP,针对数据导入以及快速聚合操作做了优化
  • Druid 不支持全文检索

2.6.2 Druid vs. Key/Value Stores (HBase/Cassandra/OpenTSDB)

  • Druid 采用列式存储,使用倒排和 bitmap索引,可以做到快速扫描相应的列

2.6.3 Druid vs. Spark

  • Spark SQL 的响应还做不到亚秒
  • Druid 可以做到超低的响应时间,例妈亚秒,而且高并发面向用户的应用

2.6.4 Druid vs. SQL-on-Hadoop (Impala/Drill/Spark SQL/Presto)

  • Druid 查询速度更快
  • 数据导入,Druid 支持实时导入,SQL-on-Hadoop 一般将数据存储在Hdfs上,Hdfs 的写入速度有可能成为瓶颈
  • SQL 支持,Druid 也支持SQL,但Druid 不支持Join 操作

2.6.5 Druid vs. Kylin

  • Kylin 不支持实时查询,Druid 支持,但是Kylin3.0 已经支持实时查询
  • Kylin 支持表连接(Join),Druid 不支持
  • Druid 可以进行数据存储,Kylin 只能进行数据的OLAP 分析

三、安装imply

3.1 Imply 介绍

  • Imply 也是Druid 的核心团队开发的,它基于Apache Druid 开发了一整套大数据分析解决方案
  • Imply 基于Druid 进行了一些组件开发,提供开源社区版本和商业版,简化了部署

3.2 集群规划

由于Druid采用分布式设计,其中不同类的的节点各司其职,故在实际部署中首选需要对各类节点进行统一规划,从功能上可以分为3个部分。

  • Master:管理节点,包含协调节点(coordinator)和统治节点(overlord),负责管理数据写入任务和容错相关处理。
  • Data:数据节点,包含历史节点和中间管理者,负责数历史数据的加载和查询和据写入处理。
  • Query:查询节点,包含查询节点和Pivot Web界面,负责提供数据查询接口和WEB交互式查询。
Druid 集群规划
主机名称IP地址角色数据库
node-01172.20.10.7zk、kafka、druid (overload、coordinator)MySQL
node-02172.20.10.8zk、kafka、druid (middleManager、historical)
node-03172.20.10.9zk、kafka、druid (broker、router)

3.3 下载imply

Imply-3.0.4 基于 apache-druid-0.15.0-Incubating

1、下载imply

下载方式:https://static.imply.io/release/imply-3.0.4.tar.gz

imply 官网:https://imply.io/

2、直接上传解压

通过浏览器下载好,通过上传工具上传到服务器 node-01中的/usr/local/ 下进行解压:

tar -zxvf imply-3.0.4.tar.gz -C /usr/local/

创建对应的软链接:

ln -s /usr/local/imply-3.0.4 /usr/local/imply

cd imply


3.4 配置 imply-3.0.4

3.4.1 mysql 中创建imply 相关的数据库

CREATE DATABASE `druid` DEFAULT CHARACTER SET utf8;
CREATE DATABASE `pivot` DEFAULT CHARACTER SET utf8;

如果zk 中也有druid,也要进行删除

zkCli.sh 
ls /
rmr /druid

注意事项:MySQL 版本必须5.5及以上版本(Druid 和 Pivot 使用utf8 字符集)


这里将个人可用配置进行分享:Apache Druid 3台集群搭建,可用配置 druid_conf.zip

配置概述

Druid集群服务众多,一套完整的Druid集群需要修改很多配置文件。我们对常用配置文件进行了整理。

配置描述文件路径 (Root Dir为 {IMPLY_HOME})修改事项
公共配置conf/druid/_common/common.runtime.properties1.需要添加一些扩展信息Extensions
2.需要配置Zookeeper集群信息
3.需要修改Metadata storage,建议选用mysql
4.需要修改Deep storage,建议选用HDFS
coordinatorconf/druid/coordinator/runtime.properties添加host(可选)
overlordconf/druid/overlord/runtime.properties添加host(可选)
historicalconf/druid/historical/runtime.properties添加hosts(可选)
middleManagerconf/druid/middleManager/runtime.properties添加host(可选)
brokerconf/druid/broker/runtime.properties添加host(可选)
routerconf/druid/router/runtime.properties添加host(可选)
pivotconf/pivot/config.yaml启动mysql存储元数据,记得mysql需要开启远程连接

正常情况下,如果我们采用的是真实的服务器,修改以上配置文件即可启动集群。不过如果使用虚拟机,需要修改下每个服务启动的JVM内存参数。主要是由大改小,改成1g即可,默认配置小于1gb的就可以不用修改。

-Xms1g
-Xmx1g
-XX:MaxDirectMemorySize=1g

涉及到的文件列表:

  • vi conf/druid/overlord/jvm.config
  • vi conf/druid/coordinator/jvm.config
  • vi conf/druid/historical/jvm.config
  • vi conf/druid/middleManager/jvm.config
  • vi conf/druid/broker/jvm.config
  • vi conf/druid/router/jvm.config

在druid中,为了提高查询效率,Broker会缓存大量的数据到内存中,可以好不夸张的说Broker内存越大,实时查询的效率越高。对于虚拟机部署的同学来讲,除了以上jvm的配置,还需要修改broker的一些缓存配置。详见配置文件。


3.4.2 修改并上传配置文件

1 修改 vi conf/druid/_common/common.runtime.properties 文件

  • 修改zookeeper 的配置
druid.extensions.directory=dist/druid/extensions
druid.extensions.hadoopDependenciesDir=dist/druid/hadoop-dependencies
druid.extensions.loadList=["mysql-metadata-storage","druid-kafka-indexing-service"]

druid.zk.service.host=node-01:2181,node-02:2181,node-03:2181
  • 修改MySQL的配置,同时需要注释掉默认的配置
druid.metadata.storage.type=mysql
druid.metadata.storage.connector.connectURI=jdbc:mysql://node-01:3306/druid
druid.metadata.storage.connector.user=root
druid.metadata.storage.connector.password=aa_bb_CC1234

2 vi conf/druid/coordinator/runtime.properties

druid.service=druid/coordinator
druid.host=node-01
druid.port=8081

druid.coordinator.startDelay=PT30S
druid.coordinator.period=PT30S      

3 vi conf/druid/overlord/runtime.properties

druid.service=druid/overlord
druid.host=node-01
druid.port=8090

druid.indexer.queue.startDelay=PT30S

druid.indexer.runner.type=remote
druid.indexer.storage.type=metadata

4 vi conf/druid/historical/runtime.properties

druid.service=druid/historical
druid.host=node-02
druid.port=8083

# HTTP server threads
druid.server.http.numThreads=40

# Processing threads and buffers
# druid.processing.buffer.sizeBytes=536870912  1048576
druid.processing.buffer.sizeBytes=1048576
# druid.processing.numMergeBuffers=7
druid.processing.numMergeBuffers=2
druid.processing.numThreads=2
druid.processing.tmpDir=var/druid/processing

# Segment storage
druid.segmentCache.locations=[{"path":"var/druid/segment-cache","maxSize"\:130000000000}]
druid.server.maxSize=130000000000

# Query cache
druid.historical.cache.useCache=true
druid.historical.cache.populateCache=true
druid.cache.type=caffeine
druid.cache.sizeInBytes=2000000000

5 vi conf/druid/middleManager/runtime.properties

druid.service=druid/middlemanager
druid.host=node-02
druid.port=8091

# Number of tasks per middleManager
druid.worker.capacity=3

# Task launch parameters
druid.indexer.runner.javaOpts=-server -Xmx2g -Duser.timezone=UTC -Dfile.encoding=UTF-8 -XX:+ExitOnOutOfMemoryError -Djava.util.logging.man
ager=org.apache.logging.log4j.jul.LogManager
druid.indexer.task.baseTaskDir=var/druid/task
druid.indexer.task.restoreTasksOnRestart=true

# HTTP server threads
druid.server.http.numThreads=40

# Processing threads and buffers
druid.processing.buffer.sizeBytes=100000000
druid.processing.numMergeBuffers=2
druid.processing.numThreads=2
druid.processing.tmpDir=var/druid/processing

# Hadoop indexing
druid.indexer.task.hadoopWorkingPath=var/druid/hadoop-tmp
druid.indexer.task.defaultHadoopCoordinates=["org.apache.hadoop:hadoop-client:2.8.3", "org.apache.hadoop:hadoop-aws:2.8.3"]

6 vi conf/druid/broker/runtime.properties

druid.service=druid/broker
druid.host=node-03
druid.port=8082

# HTTP server settings
druid.server.http.numThreads=60

# HTTP client settings
druid.broker.http.numConnections=10
druid.broker.http.maxQueuedBytes=50000000

# Processing threads and buffers
druid.processing.buffer.sizeBytes=536870912
druid.processing.numMergeBuffers=2
druid.processing.numThreads=1
druid.processing.tmpDir=var/druid/processing

# Query cache disabled -- push down caching and merging instead
druid.broker.cache.useCache=false
druid.broker.cache.populateCache=false

# SQL
druid.sql.enable=true

7 vi conf/druid/router/runtime.properties

druid.service=druid/router
druid.host=node-03
druid.port=8888

druid.processing.numThreads=1
druid.processing.buffer.sizeBytes=1000000

druid.router.defaultBrokerServiceName=druid/broker
druid.router.coordinatorServiceName=druid/coordinator
druid.router.http.numConnections=50
druid.router.http.readTimeout=PT5M
druid.router.http.numMaxThreads=100

druid.server.http.numThreads=100

druid.router.managementProxy.enabled=true

8 vi conf/pivot/config.yaml 

  • 修改mysql 的配置,同时需要注释掉默认的配置
# The port on which the Pivot server will listen on.
port: 9095

# runtime directory
varDir: var/pivot

servingMode: clustered

# User management mode
# By default Imply will not show a login screen and anyone accessing it will automatically be treated as an 'admin'
# Uncomment the line below to enable user authentication, for more info see: https://docs.imply.io/on-prem/configure/config-api
#userMode: native-users


# The initial settings that will be loaded in, in this case a connection will be created for a Druid cluster that is running locally.
initialSettings:
  connections:
    - name: druid
      type: druid
      title: My Druid
#      host: localhost:8888
      host: node-03:8888
      coordinatorHosts: ["node-01:8081"]
      overlordHosts: ["node-01:8090"]

#
# Pivot must have a state store in order to function
# The state (data cubes, dashboards, etc) can be stored in two ways.
# Choose just one option and comment out the other.
#
#  1) Stored in a sqlite file, editable at runtime with Settings View. Not suitable for running in a cluster.
#  2) Stored in a database, editable at runtime with Settings View. Works well with a cluster of Imply servers.
#

#
# 1) File-backed (sqlite) state (not suitable for running in a cluster)
#

# stateStore:
#  type: sqlite
#  connection: var/pivot/pivot-settings.sqlite

#
# 2) Database-backed state 'mysql' (MySQL) or 'pg' (Postgres)
#

stateStore:
  location: mysql
  # 这个配置必须得配,不然会报config /usr/local/imply-3.0.4/conf/pivot/config.yaml
  # t.type must be defined
  type: mysql
  connection: 'mysql://root:aa_bb_CC1234@node-01:3306/pivot'

最后进行分发到node-02, node-03

scp -r imply-3.0.4/ node-02:$PWD
scp -r imply-3.0.4/ node-03:$PWD

# 也可以通过分工脚本实现
ync.sh imply-3.0.4

配置环境变量

在每台服务器上配置  DRUID_HOME 环境变量

ln -s /usr/local/imply-3.0.4 /usr/local/imply   【每台都要创建软链接】

vi /etc/profile

# DRUID_HOME
export DRUID_HOME=/usr/local/imply
export PATH=${DRUID_HOME}/bin:$PATH

source /etc/profile 重新加载环境变量


3.5 启动 imply 集群

1、启动zk 集群

/usr/local/zk/bin/zkServer.sh start   【三台都要】

2、node-01 节点(使用外部zk 而不使用 imply 自带zk 启动 overlord 和 coordinator)

# 使用外部zk 而不使用imply 自带zk 启动overload 和 coordinator
/usr/local/imply/bin/supervise -c /usr/local/imply/conf/supervise/master-no-zk.conf

# 后台式启动
/usr/local/imply/bin/supervise -c /usr/local/imply/conf/supervise/master-no-zk.conf -daemon

3、node-02节点

/usr/local/imply/bin/supervise -c /usr/local/imply/conf/supervise/data.conf

# 后台式启动
/usr/local/imply/bin/supervise -c /usr/local/imply/conf/supervise/data.conf -daemon

4、node-03节点(启动broker 和 router)

/usr/local/imply/bin/supervise -c /usr/local/imply/conf/supervise/query.conf

# 后台式启动
/usr/local/imply/bin/supervise -c /usr/local/imply/conf/supervise/query.conf -daemon

注意事项

  • 如果希望 imply 运行在后台,在每个执行命令后面加 --daemonize
  • 注意:初次启动,需要前台启动,没启动成功的任务会反复重试启动。

  • 没有启动成功,可以去看日志。

一键启动

启动脚本

# 路径 /usr/local/imply/bin/start-druid.sh 
# 赋权 chmod +x /usr/local/imply/bin/start-druid.sh
# content
 
nohup ssh node-01 "source /etc/profile; /usr/local/imply/bin/supervise -c /usr/local/imply/conf/supervise/master-no-zk.conf -daemon" &
nohup ssh node-02 "source /etc/profile; /usr/local/imply/bin/supervise -c /usr/local/imply/conf/supervise/data.conf -daemon" &
nohup ssh node-03 "source /etc/profile; /usr/local/imply/bin/supervise -c /usr/local/imply/conf/supervise/query.conf -daemon" &


3.6 访问WebUI

组件名功能URL
broker查询服务http://node-03:8888
coordinator、overlord集群信息管理页http://node-01:8081/index.html
middleManager、historical任务管理页http://node-01:8090/console.html
pivot 可视化页http://node-03:9095/pivot/home

Druid Web界面截图:

显示服务器的存储情况

当前正在运行的任务

数据查询、可视化界面

Druid 中所有表、数据源,也是我们操作最多的界面


Apache Druid 项目一:

需求:

使用Druid 分析2020 年 8月8日 按照商口分类、商品区域的产品订单总额,订单笔数

{"timestamp":"2020-08-08T01:03.ooz","category":"手机","areaName":"北京","monye":"1450"}

如果使用SQL 进行数据查询,SQL应该这样写:

select 
	category,
	areaName,
	count(1) as total_count,
	sum(money) as total_count
from 
	order
where
	timestamp = "2020-08-08"
group by
	category,
	areaName

数据示例:

{"timestamp":"2020-08-08T01:03.00z","category":"手机","areaName":"北京","monye":"1450"}
{"timestamp":"2020-08-08T01:03.00z","category":"手机","areaName":"北京","monye":"1450"}
{"timestamp":"2020-08-08T01:03.00z","category":"家电","areaName":"北京","monye":"1550"}

{"timestamp":"2020-08-08T01:03.00z","category":"手机","areaName":"深圳","monye":"1000"}
{"timestamp":"2020-08-08T01:03.01z","category":"手机","areaName":"深圳","monye":"2000"}
{"timestamp":"2020-08-08T01:04.01z","category":"手机","areaName":"深圳","monye":"2200"}

要实现该入门案例:

1、上传没测试数据到每个Linux 服务器

  • 在一台Druid 服务器中创建 /root/druid/data1/  目录
    • mkdir -p /root/druid/data1
  • 将 druid 测试数据源 \ 商品订单数据 \ order.json 到服务器的 /root/druid/data1/  目录中
  • 将 /root/druid/data1  分发到每一台服务器

2、摄取数据到Druid 中

2.1 打开 postman,请求地址设置为 http://node-01:8090/druid/indexer/v1/task

2.2 请求方式选择为 POST

2.3 body -> raw -> JSON (application/json)

2.4 将资料中的 index_ad_event.json 文件粘贴到 postman 中

2.5 发送请求


Apache 项目二:Kafka 流式数据摄取

1. kafka 索引服务方式摄取

需求:

  • 实时摄取 Kafka 中 metrics  topic 的数据到 Druid 中

操作步骤:

1、启动Kafka 集群

#! /bin/bash
#我们将脚本存入node-01, 因为它有到node-02、node-03的免登录权限
clear

echo "--------------------- 启动kafka集群 ----------------------"
for ip in node-01 node-02 node-03
do
        echo "-----------> ssh " + $ip
        ssh root@$ip "source /etc/profile; /usr/local/kafka/bin/kafka-server-start.sh -daemon /usr/local/kafka/config/server.properties"
done

2、在Kafka 集群上创建一个名为metrics 的 topic

kafka-topics.sh --create --zookeeper node-01:2181,node-02:2181,node-03:2181 --replication-factor 1 --partitions 1 --topic metrics

3、定义摄取配置文件

  • 修改 druid 测试数据源\kafka 实时摄取数据 中的 index-metrics-kafka.json 文件中的kafka 服务器地址

4、打开postman 提交索引任务

  • 将 index-metrics-kafka.json 文件中的内容拷贝到 postman 中
  • 发送 post 请求到 http://node-01:8090/druid/indexer/v1/supervisor

在 Overlord 中可看到

测试数据格式示例:

{"time":"2020-08-23T17:57:58Z","url":"/foo/bar","user":"alice","latencyMs":32}
{"time":"2020-08-23T17:57:59Z","url":"/","user":"bob","latencyMs":11}
{"time":"2020-08-23T17:58:00Z","url":"/foo/bar","user":"bob","latencyMs":45}
  • timestampSpec 时间列,自动适应
  • dimensionsSpec 纬度,url + user
  • segmentGranularity 小时,一个小时保存一个segmentGranularity文件
  • queryGranularity 时间粒度,NONE
  • type ,按count 聚合
  • topic,指定从kafka读取哪个topic 的数据
  • consumerProperties 消费信息
    • bootstrap.servers 指下zk 地址: node-01:9092,node-02:9092,node-03:9092
    • group.id:kafka_indexing_service
  • taskCount 数量:1
  • replicas 数量:1
  • taskDuration:PT1H,默认即可

继续向Kafka 生产数据

# 创建生产者
kafka-console-producer.sh --broker-list node-01:9092,node-02:9092,node-03:9092 --topic metrics

# 创建消费者
kafka-console-consumer.sh --bootstrap-server node-01:9092,node-02:9092,node-03:9092 --topic metrics --group topic_test1_g1

摄取配置文件结构说明

1 主体结构

摄取配置文件主要由以下几个部分组成:

  • type:文件上传方式(index、index_hadoop、kafka)
  • spec
    • dataSchema:数据解析模式
    • ioConfig:数据源
    • turningConfig:优化配置(分区规则、分区大小)

{
    // 一、文件上传方式
    // 1.1 index         - 上传本地文件
    // 1.2 index_hadoop - 上传HDFS 文件
    // 1.3 kafka        - 拉取kafka 流数据
    "type": "index"
    "spec":{
            // 二、数据解析模式
            "dataSchema": {...},
            // 三、摄取数据源
            "ioConfig": {...},
            // 四、摄取过程优化配置
            "tuningConfig": {...}
    }
}

2 数据解析模式

数据解析模式,主要为针对数据文件,定义了一系列规则:

  1. 获取时间戳属性
  2. 维度属性
  3. 度量属性
  4. 定义如何进行指标计算
  5. 配置粒度规则
// 二、数据解析模式
"dataSchema": {
	// 2.1 数据源(表)
	"dataSource":"ad_event_local",
	// 2.2 解析器
	"parser":{
		// 2.2.1 解析字符串文本
		"type":"String",
		"parseSpec":{
			// 2.2.1.1 字符串文本格式为JSON
			"format": "json",
			// 2.2.1.2 指定维度列名,维度与时间一致,导入时聚合
			"dimensionSpec": {
				"dimensions": [
					"city",
					"platform"
				]
			},
			// 2.2.1.3 指定时间戳的列,以及时间戳格式化方式
			"timestampSpec": {
				"format": "auto",
				"column": "timestamp"
			}
		}
	},
	// 2.3 指标计算规则
	"metricsSpec": [
		{
			// name 表示列名
			"name": "count",
			"type": "count"
		},
		{
			// 2.3.1 聚合计算后指标的列名
			"name": "click"
			// 2.3.2 聚合函数: count、longSum、doubleSum、longMin、doubleMin、doubleMax
			"type": "longSum",
			"fieldName": "click"
		}
	]
	// 2.4 粒度规则
	"granularitySpec": {
		"type": "uniform",
		// 2.4.1 按天来生成 segment (每天生成一个segment)
		"segmentGranularity": "day",
		// 2.4.2 查询的最小粒度(最小粒度为小时)
		"queryGranularity": "hour",
		// 2.4.3 加载原始数据的时间范围,批量数据导入需要设置/流式导入无需设置
		"intervals": [
			"2020-12-01/2020-12-03"
		]
	}
}

3. 数据源配置

数据源配置主要指定:

  • 要加载数据的类型
  • 从哪儿加载数据
"ioConfig": {
	"type": "index",
	"inputSpec": {
		// 3.1 本地文件 local / HDFS使用 hadoop
		"type": "local",
		// 3.2 路径
		"baseDir": "/root/data/",
		// 3.3 只过滤出来哪个文件
		"filter": "ad_event.json"
	}
}

4. 优化配置

通常在优化配置中可以指定一些优化选项

"tuningConfig"
	"type": "index",
	// 4.1 分区类型
	"partitionsSpec": {
		"type": "hashed",
		// 4.2 每个分区的目标行数(这里配置每个分区500W行)
		"targetPartitinSize": 5000000
	}
}

5. 了解 Druid WebUI 生成 spec

  • Bootstrap servers:node-01:9092,node-02:9092,node-03:9092
  • Topic:metrics
  • Preview:预览一下数据
  • Next: Parse data:下一步
    • Parser to use:选择数据格式【json / csv / tsv / regex正则匹配】
  • Next: Parse time:下一步,选择时间格式
    • Column:时间列选择time列
    • Format:格式,可以选择自动
  • Next: Transform:
  • Next: Filter:
  • Next: Configure schema:
    • Rollup:是否开启预聚合
    • Query granularity:按小时、天、分钟
    • Add dimension:添加纬度
    • Add metric:添加指标列
  • Next: Partition:下一步优化
  • Next: Tune:优化配置项
  • Next: Publish:发布
  • Next: Edit JSON spec:这个时候就会生成json 格式文件
  • Submit:提交。  当然也可能装饰生成的Json 格式文件,可以通过 postman 发送给Druid 【Post请求、Body->raw/JSON】【另外一种提交方式】

# 查看kafka主题列表
kafka-topics.sh --list --zookeeper node-01:2181,node-02:2181,node-03:2181

# 创建topic
kafka-topics.sh --create --zookeeper node-01:2181,node-02:2181,node-03:2181 --replication-factor 3 --partitions 2 --topic metrics

# 查看topic
kafka-topics.sh --zookeeper node-01:2181,node-02:2181,node-03:2181 --topic metrics --describe

# 创建生产者
kafka-console-producer.sh --broker-list node-01:9092,node-02:9092,node-03:9092 --topic metrics

# 创建消费者
kafka-console-consumer.sh --bootstrap-server node-01:9092,node-02:9092,node-03:9092 --topic metrics --group topic_test1_g1 --from-beginning

# 删除topic
kafka-topics.sh --delete --zookeeper node-01:2181,node-02:2181,node-03:2181 --topic metrics

Kafka 测试数据:

{"time":"2020-08-23T17:57:58Z","url":"/foo/bar","user":"alice","latencyMs":32}
{"time":"2020-08-23T17:57:59Z","url":"/","user":"bob","latencyMs":11}
{"time":"2020-08-23T17:58:00Z","url":"/foo/bar","user":"bob","latencyMs":45}


Druid 数据查询

下面以【以从kafka 流式数据】为例,演示在Druid 中使用不同方式来进行数据查询、分析。

  1. JSON API 方式
  2. SQL 方式【重点】

1、JSON API 方式(了解)

Druid 最早提供JSON API 的方式查询数据,通过JSON 格式来定义各种查询组件实现数据查询。

将JSON 数据提交到:http://node-03:8082/druid/v2?pretty


2、使用JDBC查询Druid 中的数据

Druid 提供了JDBC 接口,Java Web 项目可以直接使用 JDBC 连接Druid 进行实时数据分析。

需求:

  • 获取 metrics-kafka 数据源中,不同用户的访问次数

实现步骤:

  1. 创建 druid_jdbc Maven 模块
  2. 导入依赖
  3. 编写JDBC 代码连接Druid 获取数据
    1. 加载Druid JDBC 驱动
    2. 获取Druid JDBC 连接
    3. 构建SQL 语句
    4. 构建Statement,执行SQL获取结果集
    5. 关闭Druid 连接
        <dependency>
            <groupId>org.apache.calcite.avatica</groupId>
            <artifactId>avatica</artifactId>
            <version>1.13.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.calcite.avatica/avatica-core -->
        <dependency>
            <groupId>org.apache.calcite.avatica</groupId>
            <artifactId>avatica-core</artifactId>
            <version>1.13.0</version>
        </dependency>

Java 查询示例:

package com.java.druid;

import java.sql.*;
import java.util.Properties;

/**
 * @Author:
 * @Date: 2020-12-27 22:05
 * @Version: 1.0
 * @Modified By:
 * @Description:
 */
// 使用JDBC 的方法连接Druid
public class DruidJDBCDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 1. 加载Druid 的JDBC驱动
        Class.forName("org.apache.calcite.avatica.remote.Driver");
        // 2. 获取Druid 的JDBC连接方式
        Connection connection = DriverManager.getConnection("jdbc:avatica:remote:url=http://node-03:8888/druid/v2/sql/avatica/", new Properties());
        // 3. 创建statement
        Statement statement = connection.createStatement();
        // 4. 执行sql 查询
        String sql = "select * from \"metrics\"";
        ResultSet resultSet = statement.executeQuery(sql);

        // 5. 遍历查询结果
        while (resultSet.next()) {
            String url = resultSet.getString("url");
            String user = resultSet.getString("user");
            System.out.println("user:" + user + "\t url:" +url);
        }

        // 6. 关闭连接
        resultSet.close();
        statement.close();
        connection.close();
    }
}

运行结果截图:


文章最后,给大家推荐一些受欢迎的技术博客链接

  1. JAVA相关的深度技术博客链接
  2. Flink 相关技术博客链接
  3. Spark 核心技术链接
  4. 设计模式 —— 深度技术博客链接
  5. 机器学习 —— 深度技术博客链接
  6. Hadoop相关技术博客链接
  7. 超全干货--Flink思维导图,花了3周左右编写、校对
  8. 深入JAVA 的JVM核心原理解决线上各种故障【附案例】
  9. 请谈谈你对volatile的理解?--最近小李子与面试官的一场“硬核较量”
  10. 聊聊RPC通信,经常被问到的一道面试题。源码+笔记,包懂
  11. 深入聊聊Java 垃圾回收机制【附原理图及调优方法】

欢迎扫描下方的二维码或 搜索 公众号“大数据高级架构师”,我们会有更多、且及时的资料推送给您,欢迎多多交流!

                                           

       

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不埋雷的探长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值