如果觉得这篇文章有点晦涩难懂可以先阅读我之前写的博客:https://editor.csdn.net/md/?articleId=131744687
背景
由于Druid集群角色较多,并且是一个在线实时系统,还管理着众多实时数据摄入任务等原因,运维Druid集群难度略高于其他的OLAP引擎。下面我尝试梳理一下运维Druid集群必备的细节,希望对大家有所帮助。也希望各位大佬指点出哪些地方描述不准确的地方。
数据摄入基本流程
在我们以往的运维过程中发现大部分Druid集群故障都是出现在数据摄入阶段,所以我们重点关注一下数据摄入阶段各个角色之间的协同关系,只有充分熟悉了集群中各个角色之间的交互关系,才能在集群故障中快速准确的判断出哪个角色或者哪个环节出了问题,不然的话,由于角色较多导致头脑中一团乱麻,不止所措。下图是Druid集群实时数据摄入的基本流程图,这里主要介绍实时数据摄入任务,离线数据摄入任务流程更简单,不易出故障就不做过多介绍:
步骤介绍:
- Task进程运行一段时间后会把本地segment数据 上传到hdfs
- Task发送SegmentTransactionalInsertAction请求到Overlord
- Overlord运行SegmentTransactionalInsertAction将已发布的segment信息(used=1)写入元数据库(mysql)的druid_segments表中,并更新druid_datasource表中的kafka数据偏移量
- Coordinator不断从元数据库中druid_segments拉取used=1的segment信息
- Task定时请求Coordinator,确认自己刚刚发布的segment是否被Historical加载了
- Coordinator对zk中的segment信息和druid_segments中的segment信息进行对比,从而决定分配新产生的segment
- Coordinator分配新产生的segment到Historical
- Historical不断从zk同步自己需要加载和删除的segment
- Historical下载hdfs上的数据到本地,加载segment
- Historical上报已加载的segment信息到zk,这样Coordinator和Broker能够从zk同步到新加载的segment
- Task已经收到(第5步)之前已发布的segment被某个Historical加载成功的消息
- Task进程下线提供实时查询的segment,删除在zk上segment的信息
- Task主动下线自己,并通知zk,这样Broker通过zk能感知到Task的下线
- Task退出任务进程
总结
整个流程主要是做了一件事:就是如何在保证实时数据被查询的过程中,把数据从Task进程迁移到Historical进程,在这个过程中会出现在短暂时间里实时数据存在两份的情况,即:Task进程存在一份,Historical存在一份,但是broker会优先查询Historical那份数据
Druid重要指标梳理
任务运行情况指标
task/running/count:集群中正在运行的任务数,这个数据正常情况下是很平稳。
task/pending/count:集群中等待运行的任务数,如果这个值太高说明集群中slot数不够,如果没有增加DataSource的情况下,这个值偏高,说明之前的任务运行时间过长,一直占用slot未释放。
ingest/handoff/time:集群中Segment的Handloff 时间,这个是segment从发布到被Historical加载,并被coordinator感知到的时间,如果这个时间比较之前时间比较,说明Historical 加载segment出现问题。
数据处理指标
ingest/kafka/lag 消费kafka的延迟数,延迟值不断提升一般有下面几种情况:
- kafka数据量突增现有的任务消费不过来。
- kafka分区数据倾斜,导致某几个task消费延迟
- DataSource任务有失败的情况
Segment 从task迁移指标
segment/underReplicated/count 未分配segment数,指标包含了副本的segment,该指标值偏高一般有以下几种情况:
- 存在部分Historical节点重启的情况,导致该节点的segment重新分配
- coordinator 主流程segment分配效率低或未分配segment
- 正在进行数据迁移或者增加DataSource副本数