Impala集群优化历程

一、问题背景
在一个普通的下午,已经正常运行近两年的impala集群突然开始报警,很快有用户反馈说“卡住了,查不动了。。”,紧急排查后发现有如下不普通的症状:

1、用户层,后台正在运行的查询任务并不多,但前台提交任务却迟迟不显示有任何进度或进度到一半卡住;

2、物理层,报警节点cpu异常繁忙,很快飙升到100%;

3、impala层,没有节点挂掉,statestored日志报警有很多impalad请求全量的catalog update,且单个同步量很高,接近4G,部分impalad报警Could not acquire lock for topic catalog-update. Skipping update,部分impalad报警Requesting a full topic update to recover: OutOfMemoryError: Java heap space

发现问题并不常见,而且官方社区也没有类似的问题出现,为不影响用户业务,重启impala集群后一切正常,心想可能只是虚惊一场,但后来频繁出现的类似问题让我们不得不开始了一场艰苦的战斗。

 

二、Impala介绍
在讲解我们的优化措施前,首先简单介绍一下Impala。

Impala 是一个采用MPP(大规模并行处理)架构的分布式并行计算数据库引擎,是业界主流的大数据批量分析工具

特点

基于内存计算,运行在由C++编写的后端环境,效率很高
支持列式存储如Parquet
兼容HiveSQL,用户易上手
体系架构

Impala Daemon

Impala 的核心组件是 Impala Daemon,具体在机器上就是 impalad 进程

(1)Impala Daemon 的核心功能

读写数据文件
接收通过各种方式传输来的查询,包括 impala-shell,Hue,JDBC,ODBC
coordinator将查询任务分发到executor并行执行
executor将中间查询结果传输回 coordinator
在 CDH 5.12/ Impala 2.9 之后的版本,支持将 coordinator 和 executor 分布在不同的机器上

(2)Impala Daemon内部组成

后端由C++开发,用来执行查询
前端由java开发,用来编译执行计划、存储元数据
前端被嵌到了后端程序里,共享相同的进程ID

(3)与其他角色的关系

Impala Daemon 会持续地和 StateStore 通信,以便确认哪些 Daemon 是健康的,可以接收新任务。
每当其它 Impala Daemon 创建、修改或删除了任意类型的对象,或者执行了 INSERT 或 LOAD DATA 语句,Impala Daemon 都会接收 catalogd 的广播消息
Impala StateStore

检测 Impala daemon 的健康状况,集群中只能有一个 statestore,物理表现为 statestored,当 daemon 状态异常时,statestore 会通知其他 daemon 不再发送查询到此 daemon 。
impalad与catalogd间进行元数据同步要通过statestore进行转发
Impala Catalog

catalog 负责接受Impalad的元数据请求,并与HMS、NameNode交互,加载最新的元数据,进程名为 catalogd,一个集群只需要一个 catalogd,由于请求需要经过 StateStore,所以在同一台机器上运行 catalogd 和 stateserverd 比较科学。

catalogd 的存在避免了每次由于 Impala 语句导致的元数据变化时都要执行 REFRESH 或者 INVALIDATE METADATA。不过,如果你通过 Hive 进行建表或加载数据等操作时,还是需要在查询前执行 REFRESH 和 INVALIDATE METADATA。

 

三、前期优化措施
由前文报错可知问题主要出在impalad与statestored同步元数据这块。

现有集群提供的数据规模如下:290多个库、1万7千多张表,600多万个分区,每个分区又会至少对应一个数据文件。每天运行的任务规模达到十万量级,因此元数据规模是非常庞大的,同步也是非常频繁的,为了解决问题,首先想到的办法便是减小同步规模,降低同步频率。

排查不合理的频繁sql

(1)有同学的代码出现了循环bug,不停地执行语句,这个任务每个节点要占4g内存,内存峰值390G,对集群造成了很大压力;

(2)部分同学使用impala做键值查询,经过海量批处理计算后得到结果集后只取其中一个或几个id;

排查不合理的refresh、invalidate语句

(1)禁止使用invalidate metadata,这条语句会刷新全集群的元数据,相当于重启catalogd,开销很大

(2)缩小刷新元数据的粒度,比如一个表只是某分区发生变化,使用 refresh [table] partition [partition]

(3)如果只涉及数据改变,使用refresh而不是invalidate,refresh会重用之前的元数据,仅执行文件刷新操作,invalidate是个更重量级的刷新操作,首先清空表缓存,然后重新从metastore拉取元数据,加载文件数据

(4)如果涉及元数据改变,使用 invalidate [table]

(5)在dml操作完成后执行一次刷新,而非每次查询前都刷新

降低hdfs小文件数量

海量的hdfs小文件不只会给NameNode造成沉重的负担,还会给Impala的元数据同步造成很多压力

(1)在使用Flume,Flink写入日志到HDFS过程中,会产生很多的小文件,通过例行任务合并7天前的小文件,减少小文件的存量

(2)跑hive入库任务,把src层json数据转换成ods列式数据时,使用hive on mr,减少小文件的增量,之前用的hive on spark在小文件控制这块比较差,通过配置hive参数,可以对hive on mr任务产生的小文件数进行控制

降低hive metastore压力

hive metastore是impala元数据的重要来源。

数仓部分表存在二级分区,比如在每天分区的基础上按小时分区,或按server分区,会比正常的按天分区表多一个数量级的分区,精简这部分表分区,可以降低metastore压力

分流部分任务到Hive

以下任务也适合在Hive执行:

占用内存很大
复杂的、频繁的insert
时效要求不高

 

四、柳暗花明
虽然做了一系列的优化,不过集群还是表现得不尽如人意,经进一步仔细分析底层机制后,有了一种豁然开朗的感觉。

集群底层现状是1个catalog与1个statestored部署于同一节点,133个impalad既是coordinator又是executor,再加上开启了负载均衡,这133个impalad的coordinator角色是同时起作用的,且由于机器配置情况不一样,各impalad的可用内存也是不一样的。impalad需要申请元数据锁来更新元数据,一旦更新完成又要向133个coordinator广播更新后的元数据,用户任务繁重时,锁竞争激烈,元数据同步非常频繁,coordinator的压力是很大的,降低了其执行用户任务的能力,造成任务堆积,节点不堪重负下会出现异常,申请全量的元数据同步,这进一步加重了元数据同步的负载,cpu在执行任务的比重越来越低,元数据同步的比重越来越大,造成整个集群处于停摆状态。

总的来说,一节点双角色会产生如下扩展性问题:

扮演coordinator角色会影响其执行具体查询的能力,当查询包含大量分片时coordinator会出现显著的网络和cpu开销,每个coordinator需要缓存所有表和分区的元数据,本来这些内存可用于执行joins、aggregations
大量节点扮演coordinator会产生不必要的网络开销,且由于每个coordinator都要从statestored获取metadata update,甚至会同步超时
有了思路,解决方案就容易确定了,具体方案如下:

1、寻找合适的coordinator节点,要满足cpu相对空闲,内存不小于executor两个要求;

2、确定coordinator数量,coordinator与executor的比例一般是按1:50分配的,集群繁忙可适当增加coordinator数量,因此选择5个;

3、在cdh页面建coordinator和executor角色组,划分对应节点到各自角色组,修改"Impala Daemon 命令行参数高级配置代码段(安全阀)",重启

配置Coordinator组:-is_executor=false
配置Executor组:-is_coordinator=false
4、修改haproxy impala负载均衡服务对应后端为5个coordinator节点,重新加载。

 

五、感悟

在人工智能时代,数据是一个企业最重要的战略资源之一,使数据高效的流动起来实现数据价值是一个信息企业的基本内功。随着业务的不断发展,数据量爆发式的增长,如何以最小的成本、最高的效率来存取数据是每个大数据平台团队都将面临的问题。开源节流是解决海量数据存取效率问题主要的两个抓手。在开源方面我们需要深入到大数据引擎的底层,理解系统的架构设计和实现原理,拥有源码级的问题定位和修复能力;其次在保证当前数据系统的稳定前提下,结合大数据前沿技术去不断探索和发现新的解决方案。在节流方面我们需要结合具体的数据应用场景丰富使用的案例,沉淀和完善用户手册,降低用户的学习和使用成本;我们也需要不断优化和完善数据存取中间件,化被动为主动,从工具层面降低用户对底层数据引擎的不合理使用而带来系统稳定性风险。

大数据系统作为人工智能时代的关键基础设施,不可避免地是一个支持水平扩展的系统,在很多情况下,加入更多的计算节点,确实可以提升算力。同时,大数据集群是一个动态的体系,量变产生质变,上线初期用的人比较少,存储的数据也不多,旧有的参数完全能满足使用需求,然而随着业务、数据、用户、集群规模的不断扩大,系统会变得越来越慢。大数据系统中,又有很多的模块是单点的,单点出现性能问题,加入更多的计算节点反而会加重系统的问题,就需要在架构上进行调整。

具体到大数据集群运维过程中,以下几点是我们要高度注意的:

1. 不能简单的用叠积木的方式应对业务增长,要做好性能优化调研,加深对组件内部重要机制的理解;

2. 排查问题不能流于表面,避免陷于繁琐的细节和无意义的报错;

3. 建立与应用层的需求沟通机制,向应用层提供有效的技术支持,使合适的技术应用到合适的场景。

posted @ 2025-07-01 10:39  码以致用  阅读(43)  评论(0)    收藏  举报