前言:当前业务系统的离线计算与实时计算均依赖Impala组件提供。其中离线计算为:Hive on Impala。实时计算为:kudu on impala。
问题1:SQL执行过程中内存不足,导致SQL执行超时。
异常日志如下:
代码语言:javascript复制dynamic_list_member where tenant_id = 1 and list_id in (xxxxx)) c group by list.id];
SQL state [HY000]; error code [500051]; [Cloudera][ImpalaJDBCDriver)(500051)
ERROR processing query/statement.
Error Code: 0, SQL s tate: Admission for query exceeded timeout 60000ms in pool default-pool.
Queued reason: Not enough aggregate memory available in pool de fault-pool with max mem resources 40.00 GB (configured statically).
Needed 381.04 MB but only 0 was available.
分析:
在业务系统中,接口请求有60s超时限制,在该SQL执行时,由于当时Impala服务中还有其他计算任务请求,导致该SQL任务受内存额度影响,进入等待状态,最后由于接口超时限制,该SQL任务也最终超时。在Impala中,会对SQL资源有默认的资源池限制,其参数为mem_limit
,通过该参数来约束Impala在执行SQL查询时,Impala能够使用的最大内存的宗总量。通过该参数,可以让Impala自动控制查询请求的内存总量与内存消耗。如果查询处理接近任何Impalad节点上指定的内存限制(每个查询限制或 impalad 限制),Impala则会控制SQL 操作将减少其内存消耗,例如通过将临时数据写入磁盘(称为溢出到磁盘) )。结果是查询成功完成,而不是因内存不足错误而失败。代价是由于需要额外的磁盘 I/O 写入临时数据并将其读回而导致性能下降。速度可能会显着下降。在这种场景下虽然SQL最终执行成功,但受制于后端接口与微服务的超时时间限制,最终SQL计算任务仍然超时失败。
解决办法:
根据安装了Impalad服务的节点的内存消耗情况以及在相应节点上,其他组件的内存资源消耗情况进行评估,对mem_limit的资源值进行调整。从40G--->60G。提高了资源上限,一定程度上规避了类似问题。
问题2:Impala JDBC连接数耗尽,导致业务系统在请求Impala时连接被拒绝。
异常日志如下:
代码语言:javascript复制Impala Concurrent Client ConnectionsSuppress...
There are 0 (Beeswax pool) 64 (Hive Server 2 pool) active client connections, each pool has a configured maximum of 64.
分析:客户端在请求Impala时,一般均是通过JDBC对齐进行连接。Impala自身维护了最大并发连接数,用于约束Impala能够同时处理的请求数量。该参数为--fe_service_threads
,当客户端申请连接Impala的数量超过该参数的限制时,超时后请求就会进入等待状态,当超出参数--accepted_client_cnxn_timeout
配置的超时时间阈值后,请求就会被拒绝或请求超时。因为我们的业务系统中,有大量的看板与报表需要请求Impala,所以Impala需要处理的SQL查询数量,相对也是比较高的。
解决办法:
在Impala中--fe_service_threads
的默认值为64,我们可以根据业务请求的具体数量进行评估,将其修改为128或者256,满足我们的业务系统使用即可。
注意事项:当我们调整最大并发上限参数值时,同时也意味着Impala在空闲时,需要维护更多的线程数,会一定程度上消耗集群资源,同时可能会对查询有一定性能影响。在我们请求Impala时,更多的还是建议通过线程池来对Impala进行请求。
问题3:在通过Impala查询kudu数据时,报错SQL无法在kudu表中找到某个id的数据
异常日志:
代码语言:javascript复制[Cloudera][ImpalaJDBCDriver](500051) ERROR processing query/statement.
Error Code: 0, SQL state:
Unable to advance iterator for node with id '7' for Kudu table impala::db. table':
Not found: Scanner 22317f31ecb4488980270c11822341f5 not found (it may have expired)
分析:
在该业务系统中,经常会对kudu表中的数据进行更新操作。而Impala自身维护的元数据更新又有一定时延,导致业务系统在查询时无法立刻查询到最新的数据。我们可以手动refresh Impala中相应数据表的元数据。
解决办法:
为了返回最新的数据,我们需要Impala中的元数据一直保持在最新状态,可以执行以下API,对Impala缓存中的元数据进行刷新。需要注意的是,对于Impala来说refresh元数据的代价是比较高的。非必要时不建议手动同步
代码语言:javascript复制#将数据表元数据标记为过时
INVALIDATE METADATA [[db_name.]table_name];
#刷新数据表的元数据,同步最新的元数据
REFRESH [[db_name.]table_name];
注意事项:
INVALIDATE METADATA
是一个异步操作,该操作只丢弃了目录与协调器缓存中加载的元数据。在进行该操作之后Impala的目录与协调缓存器只是知道了相应的数据库,数据表的信息,并不会同步这些表的元数据信息,只有这些表触发查询请求时才会触发这些元数据同步。REFRESH
同步重新加载元数据。REFRESH
操作的代价要低于INVALIDATE METADATA,相对更加轻量一些。如果我们通过Impala查询的是Hive的数据,或者是存储于HDFS上的数据,REFRESH
是无法感知由 HDFS 重平衡等操作触发的HDFS文件块位置的变化,因此在查询执行期间会导致远程读取,从而影响查询性能。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!