1. 问题
在一个大型的应用系统,每天都有上百亿甚至上千亿的数据需要加载到Hadoop中,随着数据量达到海量的级别,原本可以轻松搞定的事情,现在都变得非常棘手,不管是在Oracle中还是以Impala作为实时查询引擎的Hadoop中,都会遇到很多让你日思夜想,难以入眠的问题。其中的一个问题就是Impala的元数据同步问题,比如:
- 为什么HIVE中有表,但在IMPALA中查询却提示表不存在,不能自动刷新
- 为什么HDFS中有数据文件,查询却没有数据,show partitions也不能看到完整的表分区
这一个个诡异的问题都能让你茶不思,饭不想,下面我们就来分析一下Impala的元数据同步过程和它到底同步了什么
2. 分析
Impala的源代码可以在GitHub上下载或在impala.io网站上在线查看。
所有的Impala Catalog相关的操作都可以在fe目录下的代码包:com.cloudera.impala.catalog中找到。Impala有几种情况会涉及到元数据的同步操作:
1. Impala启动时
所有表都会放到 TableLoadingMgr.tableLoadingDeque_
队列中,按队列进行加载,队列的声明为:
private final LinkedBlockingDeque<TTableName> tableLoadingDeque_ =
new LinkedBlockingDeque<TTableName>();
因此可以在catalog.INFO日志中看到如下日志信息:
TableLoadingMgr.java:278] Loading next table. Remaining items in queue: 16124
TableLoadingMgr类的以下方法可以看到启动多线程进行表的Metadata加载工作:
private void startTableLoadingThreads() {
ExecutorService loadingPool = Executors.newFixedThreadPool(numLoadingThreads_);
try {
for (int i = 0; i < numLoadingThreads_; ++i) {
loadingPool.execute(new Runnable() {
@Override
public void run() {
while (true) {
try {
loadNextTable();
} catch (Exception e) {
LOG.error("Error loading table: ", e);
// Ignore exception.
}
}
}
});
}
} finally {
loadingPool.shutdown();
}
}
2. 执行INVALIDATE METADATA, REFRESH SQL语句时
这两个语句都会调用com.cloudera.impala.service.CatalogOpExecutor
类的execResetMetadata
方法,方法中的以下代码可以看出两个语句分别调用的方法:
if (req.isIs_refresh()) {
modifiedObjects.second = catalog_.rel