apache-druid在大数据行业应用中的查询性能优化

1.Coordinator瓶颈

•  实时索引任务经常被阻塞

Druid的Handoff总结如下,索引节点将Segment持久化到HDFS,然后Coordinator制定调度策略,将计划发布到ZooKeeper。历史节点从ZooKeeper获取计划后异步地加载Segment。当历史节点加载完Segment索引节点的Handoff过程才结束。这个过程中,由于Coordinator制定计划是单线程串行的,如果一次触发了大量Segment加载,执行计划制定就会很慢,从而会阻塞Handoff过程,进而索引节点所有的Slot均会被用满。

而以下过程均会触发大量Segment加载,在解决Coordinator调度性能瓶颈前, 很容易引发故障:

• 历史节点因硬件故障、GC、主动运维退出

• 调整Segment副本数、保留规则

通过火焰图对Coordinator进行Profiling最终定位了问题,如下图所示,将最耗时部分放大出来,是负载均衡策略对每个Segment要选择一个最佳的服务器。阅读源码可知其过程为,加载Segment X,需要计算它和服务器的每个Segment Y的代价Cost(X, Y),其和为服务器和Segment X的代价。假设集群有N个Segment,M个Historical节点,则一个节点宕机,有N/M个Segment需要加载,每个Segment都和剩余的N个节点计算一次代价,调度耗时和N成平方关系。

一个节点宕机调度耗时 = (N/M)个Segment * 每个Segment调度耗时 = (N/M) * N = O(N^2)

分析清楚原因后,很容易了解到Druid新版本提供了新的负载均衡策略(druid.coordinator.balancer.strategy = CachingCostBalancerStrategy),应用后调度性能提升了10000倍,原先一个历史节点宕机会阻塞Coordinator1小时到2小时,现在30秒内即可完成。

2.Overlord瓶颈

Overlord性能慢,我们发现升级到0.14后Overlord API性能较差,导致的后果是索引任务概率性因调用API超时而失败。通过Jstack分析,看到大部分的HTTP线程均为阻塞态,结合代码分析,定位到API慢的原因,如左图所示,Tranquility会定期调用Overlord API,获取所有RunningTasks,Overlord内部维护了和MySQL的连接池,该连接池默认值为8,该默认值值过小,阻塞了API处理。解决方法是增大dbcp连接池大小。druid.metadata.storage.connector.dbcp.maxTotal = 64

调整后,Overlord性能得到了大幅提升,Overlord页面打开从几十秒降低到了几秒。但意料之外的事情发生了,API处理能力增加带来了CPU的飙升,如右图所示,并且随着Tranquility任务增加CPU逐渐打满,Overlord页面性能又逐步降低。通过火焰图Profile可知,CPU主要花费在getRunningTasks的处理过程,进一步分析Tranquility源码后得知,Tranquility有一个配置项(druidBeam.overlordPollPeriod)可以控制Tranquility轮询该API的间隔,增大该间隔后问题得到了暂时缓解,但根本的解决方案还是将任务切换为KIS模式。 

3.索引成本

Druid索引成本过高。基于Druid官方文档,一个Druid索引任务需要3个核,一个核用于索引消息,一个核用于处理查询,一个核用于Handoff过程。我们采用该建议配置索引任务,压测结果是3核配置下能够支撑百万/分钟的摄入。

在最初,集群所有的索引任务都是统一配置,但实际使用过程中,大部分的索引任务根本达不到百万/分钟的消息量,造成了资源大量浪费。如下图所示,我们按照索引任务的内存使用量从高到低排序,9 GB为默认配置,80%的任务利用率低于1/3,即3 GB。我们以3 GB绘制一条横线,以内存使用最接近的任务绘制一条竖线,定义A为实际使用的内存,B为第二象限空白部分,C为第四象限空白部分,D为第一象限空白部分,则浪费的资源 = (B+C+D)的面积。

我们思考能否采取索引任务分级的策略,定义一种新的类型索引节点 – Tiny节点。Tiny节点配置改为1 core\3GB,能够满足80%小任务的资源需求,而default节点继续使用 3 core9 GB的配置,满足20%大任务的需求,在这种新的配置下,浪费的资源 = (B + C)的面积,D这一大块被省下来。简单地计算可知,在不增加机器的情况下,总Slots能够增加1倍。

默认slot资源需求为1,Tiny为1/3,调整后单位任务需要的资源 = 0.2 * 1 + 0.8 * 1/3 = 0.5

在实际操作层面,还需解决一个问题,即如何把Datasource指定给合适的Worker节点。在Druid低版本中,需要通过配置文件将每一个Datasource和Worker节点进行关联,假设有N个Datasource,M个Worker节点,这种配置的复杂度为 N * M,且无法较好地处理Worker节点负载均衡,Worker宕机等场景。在Druid 0.17中,引入了节点Category概念,只需将Datasource关联特定的Category,再将Category和Worker绑定,新的配置方法有2个Category,复杂度 =  2 * N + 2 * M。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值