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