2021SC@SDUSC
目录
概述
前面分析主要是cli用户接口和driver编译器部分。下面我将对hive的metastore模块进行分析。
hive metastore 是什么呢?
它是一个服务端,简称server。默认的端口为9083
有什么作用呢?
作用是建立起和hive客户端的连接,当客户端来请求,server去远程metastore数据库查询信息返回。
代码分析
Metastore模块在metastore目录下
该模块主要分为两个部分
HiveMetaStoreClient
是Hive连接MetaStore的客户端。HiveMetaStoreClient可以通过本地和远程两种方式访问和调用HiveMetaStore的Server。
HiveMetaStore
HiveMetaStore是HiveMetaStoreClient的服务端,可能与HiveMetaStoreClient在同一台服务器上,也可以不再统一服务器上。但是HiveMetaStore一定与实际存储Meta信息的数据库在一台服务器上。
MetaStoreClient客户端的创建
先看以下代码
private HiveConf conf = null;
private IMetaStoreClient metaStoreClient;
private UserGroupInformation owner;
// metastore calls timing information
private final Map<String, Long> metaCallTimeMap = new HashMap<String, Long>();
private static ThreadLocal<Hive> hiveDB = new ThreadLocal<Hive>() {
@Override
protected synchronized Hive initialValue() {
return null;
}
@Override
public synchronized void remove() {
if (this.get() != null) {
this.get().close();
}
super.remove();
}
};
这里声明的有hiveConf对象、metaStoreClient 、操作用户组userGroupInfomation以及调用时间Map,这里存成一个map,用来记录每一个动作的运行时长。同时维护了一个本地线程hiveDB,如果db为空的情况下,会重新创建一个Hive对象,代码如下:
public static Hive get(HiveConf c, boolean needsRefresh) throws HiveException {
Hive db = hiveDB.get();
if (db == null || needsRefresh || !db.isCurrentUserOwner()) {
if (db != null) {
LOG.debug("Creating new db. db = " + db + ", needsRefresh = " + needsRefresh +
", db.isCurrentUserOwner = " + db.isCurrentUserOwner());
}
closeCurrent();
c.set("fs.scheme.class", "dfs");
Hive newdb = new Hive(c);
hiveDB.set(newdb);
return newdb;
}
db.conf = c;
return db;
}
随后我们会发现,在创建Hive对象时,便已经将function进行注册,什么是function呢,通过上次的表结构分析,可以理解为所有udf等jar包的元数据存储。代码和解析如下:
// register all permanent functions. need improvement
static {
try {
reloadFunctions();
} catch (Exception e) {
LOG.warn("Failed to access metastore. This class should not accessed in runtime.",e);
}
}
public static void reloadFunctions() throws HiveException {
//获取 Hive对象,用于后续方法的调用
Hive db = Hive.get();
//通过遍历每一个dbName
for (String dbName : db.getAllDatabases()) {
//通过dbName查询挂在该db下的所有function的信息。
for (String functionName : db.getFunctions(dbName, "*")) {
Function function = db.getFunction(dbName, functionName);
try {
//这里的register便是将查询到的function的数据注册到Registry类中的一个Map<String,FunctionInfo>中,以便计算引擎在调用时,不必再次查询数据库。
FunctionRegistry.registerPermanentFunction(
FunctionUtils.qualifyFunctionName(functionName, dbName), function.getClassName(),
false, FunctionTask.toFunctionResource(function.getResourceUris()));
} catch (Exception e) {
LOG.warn("Failed to register persistent function " +
functionName + ":" + function.getClassName() + ". Ignore and continue.");
}
}
}
}
调用getMSC()方法,进行metadataClient客户端的创建,代码如下:
private IMetaStoreClient createMetaStoreClient() throws MetaException {
//这里实现接口HiveMetaHookLoader
HiveMetaHookLoader hookLoader = new HiveMetaHookLoader() {
@Override
public HiveMetaHook getHook(
org.apache.hadoop.hive.metastore.api.Table tbl)
throws MetaException {
try {
if (tbl == null) {
return null;
}
//根据tble的kv属性加载不同storage的实例,比如hbase、redis等等拓展存储,作为外部表进行存储
HiveStorageHandler storageHandler =
HiveUtils.getStorageHandler(conf,
tbl.getParameters().get(META_TABLE_STORAGE));
if (storageHandler == null) {
return null;
}
return storageHandler.getMetaHook();
} catch (HiveException ex) {
LOG.error(StringUtils.stringifyException(ex));
throw new MetaException(
"Failed to load storage handler: " + ex.getMessage());
}
}
};
return RetryingMetaStoreClient.getProxy(conf, hookLoader, metaCallTimeMap,
SessionHiveMetaStoreClient.class.getName());
}
以上就是MetaStoreClient的简单创建流程的分析。
下一篇,我将分析服务端创建的步骤。