Hive metastore源码阅读(一)

简介:   不要问我为什么,因为爱,哈哈哈哈。。。进入正题,最近做项目顺带学习了下hive metastore的源码,进行下知识总结。  hive metastore的整体架构如图:    一、组成结构:  如图我们可以看到,hive metastore的组成结构分为 客户端 服务端 ,那么下来我们逐一进行分析:  1、客户端     从代码的角度来看:尼玛太多了。

  不要问我为什么,因为爱,哈哈哈哈。。。进入正题,最近做项目顺带学习了下hive metastore的源码,进行下知识总结。

  hive metastore的整体架构如图:

  

  一、组成结构:

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

  1、客户端

  

   从代码的角度来看:尼玛太多了。。我们从入口HIVE开始看,可以找到MetaStoreClient客户端的创建:

  

 1   private IMetaStoreClient createMetaStoreClient() throws MetaException {
 2 
 3     HiveMetaHookLoader hookLoader = new HiveMetaHookLoader() {
 4         @Override
 5         public HiveMetaHook getHook(
 6           org.apache.hadoop.hive.metastore.api.Table tbl)
 7           throws MetaException {
 8 
 9           try {
10             if (tbl == null) {
11               return null;
12             }
13             HiveStorageHandler storageHandler =
14               HiveUtils.getStorageHandler(conf,
15                 tbl.getParameters().get(META_TABLE_STORAGE));
16             if (storageHandler == null) {
17               return null;
18             }
19             return storageHandler.getMetaHook();
20           } catch (HiveException ex) {
21             LOG.error(StringUtils.stringifyException(ex));
22             throw new MetaException(
23               "Failed to load storage handler:  " + ex.getMessage());
24           }
25         }
26       };
27     return RetryingMetaStoreClient.getProxy(conf, hookLoader, metaCallTimeMap,
28         SessionHiveMetaStoreClient.class.getName());
29   }

  我们可以看到,创建MetaStoreClient中,创建了HiveMetaHook,这个Hook的作用在于,每次对meta进行操作的时候,比如createTable的时候,如果建表的存储方式不是文件,比如集成hbase,HiveMetaStoreClient会调用hook的接口方法preCreateTable,进行建表前的准备,用来判断外部表与内部表,如果中途有失败的话,依旧调用hook中的rollbackCreateTable进行回滚。

 1   public void createTable(Table tbl, EnvironmentContext envContext) throws AlreadyExistsException,
 2       InvalidObjectException, MetaException, NoSuchObjectException, TException {
 3     HiveMetaHook hook = getHook(tbl);
 4     if (hook != null) {
 5       hook.preCreateTable(tbl);
 6     }
 7     boolean success = false;
 8     try {
 9       // Subclasses can override this step (for example, for temporary tables)
10       create_table_with_environment_context(tbl, envContext);
11       if (hook != null) {
12         hook.commitCreateTable(tbl);
13       }
14       success = true;
15     } finally {
16       if (!success && (hook != null)) {
17         hook.rollbackCreateTable(tbl);
18       }
19     }
20   }

  在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,来决定是在本地创建服务端,这里为在本地:

 1   public HiveMetaStoreClient(HiveConf conf, HiveMetaHookLoader hookLoader)
 2     throws MetaException {
 3 
 4     this.hookLoader = hookLoader;
 5     if (conf == null) {
 6       conf = new HiveConf(HiveMetaStoreClient.class);
 7     }
 8     this.conf = conf;
 9     filterHook = loadFilterHooks();
10 
11     String msUri = conf.getVar(HiveConf.ConfVars.METASTOREURIS);
12     localMetaStore = HiveConfUtil.isEmbeddedMetaStore(msUri);
13     if (localMetaStore) {
14       // instantiate the metastore server handler directly instead of connecting
15       // through the network
16       client = HiveMetaStore.newRetryingHMSHandler("hive client", conf, true);
17       isConnected = true;
18       snapshotActiveConf();
19       return;
20     }

  随后,创建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用于对每一步事件的监听。

 1       initListeners = MetaStoreUtils.getMetaStoreListeners(
 2           MetaStoreInitListener.class, hiveConf,
 3           hiveConf.getVar(HiveConf.ConfVars.METASTORE_INIT_HOOKS));
 4       for (MetaStoreInitListener singleInitListener: initListeners) {
 5           MetaStoreInitContext context = new MetaStoreInitContext();
 6           singleInitListener.onInit(context);
 7       }
 8 
 9       String alterHandlerName = hiveConf.get("hive.metastore.alter.impl",
10           HiveAlterHandler.class.getName());
11       alterHandler = (AlterHandler) ReflectionUtils.newInstance(MetaStoreUtils.getClass(
12           alterHandlerName), hiveConf);
13       wh = new Warehouse(hiveConf);
14 
15       synchronized (HMSHandler.class) {
16         if (currentUrl == null || !currentUrl.equals(MetaStoreInit.getConnectionURL(hiveConf))) {
17           createDefaultDB();
18           createDefaultRoles();
19           addAdminUsers();
20           currentUrl = MetaStoreInit.getConnectionURL(hiveConf);
21         }
22       }
23 
24       if (hiveConf.getBoolean("hive.metastore.metrics.enabled", false)) {
25         try {
26           Metrics.init();
27         } catch (Exception e) {
28           // log exception, but ignore inability to start
29           LOG.error("error in Metrics init: " + e.getClass().getName() + " "
30               + e.getMessage(), e);
31         }
32       }
33 
34       preListeners = MetaStoreUtils.getMetaStoreListeners(MetaStorePreEventListener.class,
35           hiveConf,
36           hiveConf.getVar(HiveConf.ConfVars.METASTORE_PRE_EVENT_LISTENERS));
37       listeners = MetaStoreUtils.getMetaStoreListeners(MetaStoreEventListener.class, hiveConf,
38           hiveConf.getVar(HiveConf.ConfVars.METASTORE_EVENT_LISTENERS));
39       listeners.add(new SessionPropertiesListener(hiveConf));
40       endFunctionListeners = MetaStoreUtils.getMetaStoreListeners(
41           MetaStoreEndFunctionListener.class, hiveConf,
42           hiveConf.getVar(HiveConf.ConfVars.METASTORE_END_FUNCTION_LISTENERS));

  同时创建了AlterHandler,它是HiveAlterHandler的接口,是将修改表和修改partition的操作抽离了出来单独实现(修改表很复杂的。。)。

 1 public interface AlterHandler extends Configurable {
 2 
 3   /**
 4    * handles alter table
 5    *
 6    * @param msdb
 7    *          object to get metadata
 8    * @param wh
 9    *          TODO
10    * @param dbname
11    *          database of the table being altered
12    * @param name
13    *          original name of the table being altered. same as
14    *          <i>newTable.tableName</i> if alter op is not a rename.
15    * @param newTable
16    *          new table object
17    * @throws InvalidOperationException
18    *           thrown if the newTable object is invalid
19    * @throws MetaException
20    *           thrown if there is any other error
21    */
22   public abstract void alterTable(RawStore msdb, Warehouse wh, String dbname,
23       String name, Table newTable) throws InvalidOperationException,
24       MetaException;
25 
26   /**
27    * handles alter table, the changes could be cascaded to partitions if applicable
28    *
29    * @param msdb
30    *          object to get metadata
31    * @param wh
32    *          Hive Warehouse where table data is stored
33    * @param dbname
34    *          database of the table being altered
35    * @param name
36    *          original name of the table being altered. same as
37    *          <i>newTable.tableName</i> if alter op is not a rename.
38    * @param newTable
39    *          new table object
40    * @param cascade
41    *          if the changes will be cascaded to its partitions if applicable
42    * @throws InvalidOperationException
43    *           thrown if the newTable object is invalid
44    * @throws MetaException
45    *           thrown if there is any other error
46    */
47   public abstract void alterTable(RawStore msdb, Warehouse wh, String dbname,
48       String name, Table newTable, boolean cascade) throws InvalidOperationException,
49       MetaException;

  最重要的是RawStore的创建。RawStore不光是定义了一套最终的物理操作,使用JDO将一个对象当作表进行存储。ObjectStore中的transaction机制也是通过JDO提供的transaction实现的。当commit失败时,将rollback所有操作。

  

 1   @Override
 2   public void createDatabase(Database db) throws InvalidObjectException, MetaException {
 3     boolean commited = false;
 4     MDatabase mdb = new MDatabase();
 5     mdb.setName(db.getName().toLowerCase());
 6     mdb.setLocationUri(db.getLocationUri());
 7     mdb.setDescription(db.getDescription());
 8     mdb.setParameters(db.getParameters());
 9     mdb.setOwnerName(db.getOwnerName());
10     PrincipalType ownerType = db.getOwnerType();
11     mdb.setOwnerType((null == ownerType ? PrincipalType.USER.name() : ownerType.name()));
12     try {
13       openTransaction();
14       pm.makePersistent(mdb);
15       commited = commitTransaction();
16     } finally {
17       if (!commited) {
18         rollbackTransaction();
19       }
20     }
21   }
22 
23   @SuppressWarnings("nls")
24   private MDatabase getMDatabase(String name) throws NoSuchObjectException {
25     MDatabase mdb = null;
26     boolean commited = false;
27     try {
28       openTransaction();
29       name = HiveStringUtils.normalizeIdentifier(name);
30       Query query = pm.newQuery(MDatabase.class, "name == dbname");
31       query.declareParameters("java.lang.String dbname");
32       query.setUnique(true);
33       mdb = (MDatabase) query.execute(name);
34       pm.retrieve(mdb);
35       commited = commitTransaction();
36     } finally {
37       if (!commited) {
38         rollbackTransaction();
39       }
40     }
41     if (mdb == null) {
42       throw new NoSuchObjectException("There is no database named " + name);
43     }
44     return mdb;
45   }

  今晚就到这里。。。自己摸索,如有错误,还望指出谢谢~

   

相关实践学习
lindorm多模间数据无缝流转
展现了Lindorm多模融合能力——用kafka API写入,无缝流转在各引擎内进行数据存储和计算的实验。
云数据库HBase版使用教程
&nbsp; 相关的阿里云产品:云数据库 HBase 版 面向大数据领域的一站式NoSQL服务,100%兼容开源HBase并深度扩展,支持海量数据下的实时存储、高并发吞吐、轻SQL分析、全文检索、时序时空查询等能力,是风控、推荐、广告、物联网、车联网、Feeds流、数据大屏等场景首选数据库,是为淘宝、支付宝、菜鸟等众多阿里核心业务提供关键支撑的数据库。 了解产品详情:&nbsp;https://cn.aliyun.com/product/hbase &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
6月前
|
SQL 分布式计算 数据库
【大数据技术Spark】Spark SQL操作Dataframe、读写MySQL、Hive数据库实战(附源码)
【大数据技术Spark】Spark SQL操作Dataframe、读写MySQL、Hive数据库实战(附源码)
229 0
|
3月前
|
SQL 存储 关系型数据库
|
6月前
|
SQL Java Maven
hive-3.0.0源码编译详解
hive-3.0.0源码编译详解
54 0
|
SQL 分布式计算 Java
浅析 hive udaf 的正确编写方式- 论姿势的重要性-系列四-如何直接访问metastore service(附源码)
浅析 hive udaf 的正确编写方式- 论姿势的重要性-系列四-如何直接访问metastore service(附源码)
|
SQL 运维 大数据
如何获取大数据平台 CDH 中 hive metastore db 的用户名和密码?
如何获取大数据平台 CDH 中 hive metastore db 的用户名和密码?
如何获取大数据平台 CDH 中 hive metastore db 的用户名和密码?
|
SQL 存储 大数据
关于数据仓库的Hive的Hive架构的MetaStore元数据服务
随着大数据技术的不断发展,数据仓库成为了企业中不可或缺的一部分。而Hive作为一种开源的数据仓库系统,因其易于使用和高效处理等特点,成为了许多企业的首选。然而,对于普通用户来说,直接使用Hive的命令行工具进行操作并不方便。因此,开发者社区中涌现出了大量的Hive GUI工具,其中最为流行的就是Web GUI工具。
304 2
|
SQL 存储 分布式计算
Hive 2.1.1 MetaException(在metastore中找不到消息:版本信息)
Hive 2.1.1 MetaException(在metastore中找不到消息:版本信息)
374 0
|
SQL HIVE
解决启动Hive报错Hive Schema version 2.3.0 does not match metastore‘s schema version 1.2.0 Metastore is not
解决启动Hive报错Hive Schema version 2.3.0 does not match metastore‘s schema version 1.2.0 Metastore is not
211 0
|
SQL 分布式计算 Java
spark 对于hive metastore的兼容性随笔--通过classloader实现
spark 对于hive metastore的兼容性随笔--通过classloader实现
480 0
|
SQL 存储 分布式计算
Hive简介及源码编译
Hive是一个基于Hadoop的数据仓库,可以将结构化数据映射成一张表,并提供类SQL的功能,最初由Facebook提供,使用HQL作为查询接口、HDFS作为存储底层、MapReduce作为执行层,设计目的是让SQL技能良好,但Java技能较弱的分析师可以查询海量数据,2008年facebook把Hive项目贡献给Apache。Hive提供了比较完整的SQL功能(本质是将SQL转换为MapReduce),自身最大的缺点就是执行速度慢。Hive有自身的元数据结构描述,可以使用MySql\ProstgreSql\oracle 等关系型数据库来进行存储,但请注意Hive中的所有数据都存储在HDFS中
430 0
Hive简介及源码编译