Hive metastore源码阅读(一)
不要问我为什么,因为爱,哈哈哈哈。。。进入正题,最近做项目顺带学习了下hive metastore的源码,进行下知识总结。
hive metastore的整体架构如图:

一、组成结构:
如图我们可以看到,hive metastore的组成结构分为 客户端 服务端 ,那么下来我们逐一进行分析:
1、客户端

从代码的角度来看:尼玛太多了。。我们从入口HIVE开始看,可以找到MetaStoreClient客户端的创建:
private IMetaStoreClient createMetaStoreClient() throws MetaException {
HiveMetaHookLoader hookLoader = new HiveMetaHookLoader() {
@Override
public HiveMetaHook getHook(
org.apache.hadoop.hive.metastore.api.Table tbl)
throws MetaException {
try {
if (tbl == null) {
return null;
}
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中,创建了HiveMetaHook,这个Hook的作用在于,每次对meta进行操作的时候,比如createTable的时候,如果建表的存储方式不是文件,比如集成hbase,HiveMetaStoreClient会调用hook的接口方法preCreateTable,进行建表前的准备,用来判断外部表与内部表,如果中途有失败的话,依旧调用hook中的rollbackCreateTable进行回滚。
public void createTable(Table tbl, EnvironmentContext envContext) throws AlreadyExistsException,
InvalidObjectException, MetaException, NoSuchObjectException, TException {
HiveMetaHook hook = getHook(tbl);
if (hook != null) {
hook.preCreateTable(tbl);
}
boolean success = false;
try {
// Subclasses can override this step (for example, for temporary tables)
create_table_with_environment_context(tbl, envContext);
if (hook != null) {
hook.commitCreateTable(tbl);
}
success = true;
} finally {
if (!success && (hook != null)) {
hook.rollbackCreateTable(tbl);
}
}
}
在hbase表不存在的情况下,不能create external table ,会报doesn't exist while the table is declared as an external table,那么需直接创建create table 创建一个指向hbase的hive表。
建表语句如下:
CREATE TABLE hbase_table_1(key int, value string) /
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,cf1:val")
TBLPROPERTIES ("hbase.table.name" = "tableName", "hbase.mapred.output.outputtable" = "tableName");
代码请查看HBaseStorageHandler的preCreateTable方法,这里就不贴出来啦。
随之回归Hive类,Hive类可以说是整个元数据DDL操作的最顶层抽象。HiveMetaStoreClient实现了IMetaStoreClient的接口,在创建HiveMetaStoreClient时,会创建于server段HiveMetaStore的链接,并且会通过检查hive.metastore.local是否为true,来决定是在本地创建服务端,这里为在本地:
public HiveMetaStoreClient(HiveConf conf, HiveMetaHookLoader hookLoader)
throws MetaException { this.hookLoader = hookLoader;
if (conf == null) {
conf = new HiveConf(HiveMetaStoreClient.class);
}
this.conf = conf;
filterHook = loadFilterHooks(); String msUri = conf.getVar(HiveConf.ConfVars.METASTOREURIS);
localMetaStore = HiveConfUtil.isEmbeddedMetaStore(msUri);
if (localMetaStore) {
// instantiate the metastore server handler directly instead of connecting
// through the network
client = HiveMetaStore.newRetryingHMSHandler("hive client", conf, true);
isConnected = true;
snapshotActiveConf();
return;
}
随后,创建server端的HiveMetaStore.HMSHandler,HMSHandler继承自IHMSHandler,而IHMSHandler又继承自ThriftHiveMetastore.Iface,在HMSHandler中实现了所有操作的对外方法:
public class ThriftHiveMetastore {
/**
* This interface is live.
*/
public interface Iface extends com.facebook.fb303.FacebookService.Iface {
public String getMetaConf(String key) throws MetaException, org.apache.thrift.TException;
public void setMetaConf(String key, String value) throws MetaException, org.apache.thrift.TException;
public void create_database(Database database) throws AlreadyExistsException, InvalidObjectException, MetaException, org.apache.thrift.TException;
public Database get_database(String name) throws NoSuchObjectException, MetaException, org.apache.thrift.TException;
public void drop_database(String name, boolean deleteData, boolean cascade) throws NoSuchObjectException, InvalidOperationException, MetaException, org.apache.thrift.TException;
public List<String> get_databases(String pattern) throws MetaException, org.apache.thrift.TException;
public List<String> get_all_databases() throws MetaException, org.apache.thrift.TException;
public void alter_database(String dbname, Database db) throws MetaException, NoSuchObjectException, org.apache.thrift.TException;
public Type get_type(String name) throws MetaException, NoSuchObjectException, org.apache.thrift.TException;
public boolean create_type(Type type) throws AlreadyExistsException, InvalidObjectException, MetaException, org.apache.thrift.TException;
public boolean drop_type(String type) throws MetaException, NoSuchObjectException, org.apache.thrift.TException;
......
在创建HiveMetaStore的init方法中,同时创建了三种Listener---MetaStorePreEventListener,MetaStoreEventListener,MetaStoreEndFunctionListener用于对每一步事件的监听。
initListeners = MetaStoreUtils.getMetaStoreListeners(
MetaStoreInitListener.class, hiveConf,
hiveConf.getVar(HiveConf.ConfVars.METASTORE_INIT_HOOKS));
for (MetaStoreInitListener singleInitListener: initListeners) {
MetaStoreInitContext context = new MetaStoreInitContext();
singleInitListener.onInit(context);
} String alterHandlerName = hiveConf.get("hive.metastore.alter.impl",
HiveAlterHandler.class.getName());
alterHandler = (AlterHandler) ReflectionUtils.newInstance(MetaStoreUtils.getClass(
alterHandlerName), hiveConf);
wh = new Warehouse(hiveConf); synchronized (HMSHandler.class) {
if (currentUrl == null || !currentUrl.equals(MetaStoreInit.getConnectionURL(hiveConf))) {
createDefaultDB();
createDefaultRoles();
addAdminUsers();
currentUrl = MetaStoreInit.getConnectionURL(hiveConf);
}
} if (hiveConf.getBoolean("hive.metastore.metrics.enabled", false)) {
try {
Metrics.init();
} catch (Exception e) {
// log exception, but ignore inability to start
LOG.error("error in Metrics init: " + e.getClass().getName() + " "
+ e.getMessage(), e);
}
} preListeners = MetaStoreUtils.getMetaStoreListeners(MetaStorePreEventListener.class,
hiveConf,
hiveConf.getVar(HiveConf.ConfVars.METASTORE_PRE_EVENT_LISTENERS));
listeners = MetaStoreUtils.getMetaStoreListeners(MetaStoreEventListener.class, hiveConf,
hiveConf.getVar(HiveConf.ConfVars.METASTORE_EVENT_LISTENERS));
listeners.add(new SessionPropertiesListener(hiveConf));
endFunctionListeners = MetaStoreUtils.getMetaStoreListeners(
MetaStoreEndFunctionListener.class, hiveConf,
hiveConf.getVar(HiveConf.ConfVars.METASTORE_END_FUNCTION_LISTENERS));
同时创建了AlterHandler,它是HiveAlterHandler的接口,是将修改表和修改partition的操作抽离了出来单独实现(修改表很复杂的。。)。
public interface AlterHandler extends Configurable {
/**
* handles alter table
*
* @param msdb
* object to get metadata
* @param wh
* TODO
* @param dbname
* database of the table being altered
* @param name
* original name of the table being altered. same as
* <i>newTable.tableName</i> if alter op is not a rename.
* @param newTable
* new table object
* @throws InvalidOperationException
* thrown if the newTable object is invalid
* @throws MetaException
* thrown if there is any other error
*/
public abstract void alterTable(RawStore msdb, Warehouse wh, String dbname,
String name, Table newTable) throws InvalidOperationException,
MetaException;
/**
* handles alter table, the changes could be cascaded to partitions if applicable
*
* @param msdb
* object to get metadata
* @param wh
* Hive Warehouse where table data is stored
* @param dbname
* database of the table being altered
* @param name
* original name of the table being altered. same as
* <i>newTable.tableName</i> if alter op is not a rename.
* @param newTable
* new table object
* @param cascade
* if the changes will be cascaded to its partitions if applicable
* @throws InvalidOperationException
* thrown if the newTable object is invalid
* @throws MetaException
* thrown if there is any other error
*/
public abstract void alterTable(RawStore msdb, Warehouse wh, String dbname,
String name, Table newTable, boolean cascade) throws InvalidOperationException,
MetaException;
最重要的是RawStore的创建。RawStore不光是定义了一套最终的物理操作,使用JDO将一个对象当作表进行存储。ObjectStore中的transaction机制也是通过JDO提供的transaction实现的。当commit失败时,将rollback所有操作。
@Override
public void createDatabase(Database db) throws InvalidObjectException, MetaException {
boolean commited = false;
MDatabase mdb = new MDatabase();
mdb.setName(db.getName().toLowerCase());
mdb.setLocationUri(db.getLocationUri());
mdb.setDescription(db.getDescription());
mdb.setParameters(db.getParameters());
mdb.setOwnerName(db.getOwnerName());
PrincipalType ownerType = db.getOwnerType();
mdb.setOwnerType((null == ownerType ? PrincipalType.USER.name() : ownerType.name()));
try {
openTransaction();
pm.makePersistent(mdb);
commited = commitTransaction();
} finally {
if (!commited) {
rollbackTransaction();
}
}
} @SuppressWarnings("nls")
private MDatabase getMDatabase(String name) throws NoSuchObjectException {
MDatabase mdb = null;
boolean commited = false;
try {
openTransaction();
name = HiveStringUtils.normalizeIdentifier(name);
Query query = pm.newQuery(MDatabase.class, "name == dbname");
query.declareParameters("java.lang.String dbname");
query.setUnique(true);
mdb = (MDatabase) query.execute(name);
pm.retrieve(mdb);
commited = commitTransaction();
} finally {
if (!commited) {
rollbackTransaction();
}
}
if (mdb == null) {
throw new NoSuchObjectException("There is no database named " + name);
}
return mdb;
}
今晚就到这里。。。自己摸索,如有错误,还望指出谢谢~
Hive metastore源码阅读(一)的更多相关文章
- Hive metastore源码阅读(三)
上次写了hive metastore的partition的生命周期,但是简略概括了下alter_partition的操作,这里补一下alter_partition,因为随着项目的深入,发现它涉及的地方 ...
- Hive metastore源码阅读(二)
最近随着项目的深入,发现hive meta有些弊端,就是你会发现它的元数据操作与操作物理集群的代码耦合在一起,非常不利于扩展.比如:在create_table的时候同时进行路径校验及创建,如下代码: ...
- Hive cli源码阅读和梳理
对Cli的重新认识*). hive cli有两种模式, 本地模式: 采用持有的driver对象来处理, 远程模式: 通过连接HiveServer来实现, 由此可见之前的架构图中的描述还是模糊且带有误导 ...
- 详细讲解Hadoop源码阅读工程(以hadoop-2.6.0-src.tar.gz和hadoop-2.6.0-cdh5.4.5-src.tar.gz为代表)
首先,说的是,本人到现在为止,已经玩过. 对于,这样的软件,博友,可以去看我博客的相关博文.在此,不一一赘述! Eclipse *版本 Eclipse *下载 Jd ...
- spark源码阅读
根据spark2.2的编译顺序来确定源码阅读顺序,只阅读核心的基本部分. 1.common目录 ①Tags②Sketch③Networking④Shuffle Streaming Service⑤Un ...
- fw: 专访许鹏:谈C程序员修养及大型项目源码阅读与学习
C家最近也有一篇关于如何阅读大型c项目源代码的文章,学习..融合.. -------------------- ref:http://www.csdn.net/article/2014-06-05 ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- 【原】FMDB源码阅读(二)
[原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...
- 【原】FMDB源码阅读(一)
[原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...
随机推荐
- Tomcat软件使用常见问题
Tomcat软件使用常见问题 tomcat软件使用的常见问题 1)闪退问题 原因:tomcat软件是java语言开发的. tomcat软件启动时,会默认到系统的环境变量中查找一个名称叫JAVA_HOM ...
- NopCommerce用core重写ef
最近看了NopCommerce源码,用core学习着写了一个项目,修改的地方记录下.项目地址 NopCommerce框架出来好久了.18年的第一季度 懒加载出来后也会全部移动到.net core.那么 ...
- 为了解决linux配置Nginx 只能关闭防火墙才能访问的问题
使用Nginx和iptables做访问权限控制(IP和MAC) 之前配置的服务器,相当于对整个内网都是公开的,而且,除了可以通过80端口的nginx来间接访问各项服务,也可以绕过nginx,直 ...
- mysql 远程连接数据库的二种方法
一.连接远程数据库: 1.显示密码 如:MySQL 连接远程数据库(192.168.5.116),端口"3306",用户名为"root",密码"123 ...
- thinkphp开发微信公众号时,验证基本配置提示请求url超时
原因在index.php入口文件中必须有define('APP_NAME', 'Weixin'); 服务器url:http://bxu2713700584.my3w.com/Weixin/Index/ ...
- ngRx 官方示例分析 - 6 - Effect
@ngrx/effect 前面我们提到,在 Book 的 reducer 中,并没有 Search 这个 Action 的处理,由于它需要发出一个异步的请求,等到请求返回前端,我们需要根据返回的结果来 ...
- Java数据库基础(JDBC)
JDBC(Java Data Base Connectivity):SUN公司为了简化统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC: 这样应用程序就不需要关注数据库底层的详细 ...
- Hibernate 的原生 SQL 查询
Hibernate除了支持HQL查询外,还支持原生SQL查询. 对原生SQL查询执行的控制是通过SQLQuery接口进行的,通过执行Session.createSQLQuery()获取 ...
- bxslider使用教程
bxSlider下载+参数说明 "bxSlider"就是一款响应式的幻灯片js插件 bxSlider特性 充分响应各种设备,适应各种屏幕: 支持多种滑动模式,水平.垂直以及淡入淡出 ...
- Github终于连上了hexo
2018-01-2722:59:28 我的妈呀,看看这感人的网速,哎不想吐槽在中国连外网的速度 总结一下连接过程吧 漫漫长征路,难的要死. 一.github的注册和使用不再详述 二.Git Desk ...