Hive 中创建 UDF 时长时间等待

当在 Hive 中执行:

CREATE TEMPORARY FUNCTION ...

Hive 一直处于等待,且很长时间没有结果。看上去是像在等待某个任务完成。于是顺手看了下源码。

先去下载一份相同版本的源码,简单看了下目录命名方式,和 HQL 相关的代码应该在 ql 目录中。

为了找到相关函数,根据 Hive 项目函数的命名风格,可以推测相关处理函数应该包含“createTemporary”关键字。用 fgrep 搜索下:

$ fgrep createTemporary -r -n ql/*

搜索结果中,可以看到一条定义 createTemporaryFunction 的语句:

ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionTask.java:169:  private int createTemporaryFunction(CreateFunctionDesc createFunctionDesc) {

打开该文件,跟踪下相关流程,该函数会调用 FunctionRegistry.registerTemporaryFunction 来注册函数:

boolean registered = FunctionRegistry.registerTemporaryFunction(
  createFunctionDesc.getFunctionName(),
  udfClass);

继续用 fgrep 跟踪 FunctionRegistry.registerTemporaryFunction,在文件 ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java 中找到。关键代码如下:

case UDF:
  FunctionRegistry.registerTemporaryUDF(
    functionName, (Class<? extends UDF>) udfClass, false);

接着再跟踪 FunctionRegistry.registerTemporaryUDF,在该函数实现中注意到:

mFunctions.put(functionName.toLowerCase(), fI);

mFunctions 是个集合对象,找到它的定义:

static Map<String, FunctionInfo> mFunctions = Collections.synchronizedMap(new LinkedHashMap<String, FunctionInfo>());

可以看到 mFunctions 实际上是一个线程安全的 Map 对象,所以我猜测卡死的原因应该是因为多线程抢占的问题。

带着跟死锁有关的关键字在 Google 搜索了下,找到 Hive 的 issue 列表跟我一模一样的问题:

https://issues.apache.org/jira/browse/HIVE-9203

该问题引申到另外一个 issue:https://issues.apache.org/jira/browse/HIVE-9199

从这个问题来看,确实是多线程抢占导致的。官方表示在 1.1.0 版本中修复这个问题,但因为是公司集群,我不能通过升级 Hive 来解决这个问题,于是我想有不有线程相关的配置可以解决这个问题,之后在 Hive 文档里找到相关设置,执行下面语句即可:

set hive.support.concurrency=false