Hive Delegation Token 揭秘

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
大数据开发治理平台 DataWorks,不限时长
简介: 本篇文章是由一次 Hive 集群生产优化而引出的知识点,供大家参考

前言

  本篇文章是由一次 Hive 集群生产优化而引出的知识点,供大家参考


一、Hive Delegation Token是什么?

  要说 Hive Delegation Token,首先简单了解一下 Delegation Token。在网上关于大数据领域里最相关且提到最多的就是 HDFS Delegation Token 有关的文章了,Hive Delegation Token这个提法很少。其实 Hive 的这个东西也是和 HDFS 的有关系,所以咱先提一下 HDFS Delegation Token。HDFS Delegation Token 一言以蔽之就是 Hadoop 里一种轻量级认证方法,客户端创建连接时 NameNode 会创建并保存在内存里,更多的细节大家可以自行百度。^ ^

  需要多提一下的是,HDFS 的这套 Delegation Token 机制,不仅仅是 HDFS 的实现,而是为整个大数据领域的框架提供的一套解决方案,其他和 HDFS 有关的组件,也会基于该方案来实现自己的 Delegation Token,比如 Yarn、HBase 等等,当然也包含本篇文章的主人公 Hive,那显而易见,Hive 实现的当然就叫 Hive Delegation Token 了(下文简称 token )。

二、问题产生背景

  某一天天气很好,笔者看了一下生产环境 HMS (Hive Metastore) 使用的 Mysql 的监控信息,观察到每隔一个小时,数据库就有一次高 ops 现象,像一日三餐一样非常稳定,高出平时正常值超过 3 倍。于是笔者就从这个现象入手开始排查问题的根因,排查过程枯燥乏味暂且略过,直接来干货上结论!

三、结论

  每个 HS2(HiveServer2) 和 HMS 都会起一个守护线程,每隔一个小时该线程都会去清理 MySql 中 Hive 的过期 token。目前存储 token 的表里面长期保持有几万条 token,每次清理时,每个 HS2 和 HMS 都会逐条取出每一条 token 进行过期时间的判断,如果过期就删除。集群中的 HS2 + HMS 的实例数量加起来有几十个,每隔一个小时,这几十个进程的清理操作集中到一起(几十乘以几万就有几百万的数据库操作),导致了上述背景中数据库的毛刺现象。

四、Hive Delegation Token 维护逻辑

感兴趣的童鞋,我们就来一起看下更细节的一些东西。~

  • 当前 Hive 默认的 token 维护策略为:

    1. 新作业(Spark 等)和 HS2 建立新连接的时候新增 token ,默认当前有效时间为 1 天,最大有效时间为 7 天,token 被存储在数据库 hive.delegation_tokens 中
    2. 作业每过 1 个小时更新 token 的有效时间。更新后的有效时间为更新时间点往后 24h

    3. 清理 token 的逻辑为每 1 个小时遍历 delegation_tokens,每个 HS2 和 HMS 都会维护一个清理线程,其逻辑为
      3.1. 一次性拿到全部的 TokenIdentifier 先判断是否大于最大有效时间,超过了就删掉
      3.2. 没超过再通过 TokenIdentifier 去表 delegation_tokens 中取 TokenInfo ,判断是否大于当前有效时间,超过了就删掉

  • 清理线程的启动和处理逻辑:

    实际的清理线程是 ExpiredTokenRemover,是 TokenStoreDelegationTokenSecretManager 的内部类

    HiveServer2 和 Hive Metastore 服务,在启动的时候都会启动一个 HadoopThriftAuthBridge 对象,然后会通过这个对象的 startDelegationTokenSecretManager 方法来启动 TokenStoreDelegationTokenSecretManager ,然后在 TokenStoreDelegationTokenSecretManager 的 startThreads 方法里面实例化 ExpiredTokenRemover 线程并启动。

Now show the code !

protected class ExpiredTokenRemover extends Thread {
   
  private long lastMasterKeyUpdate;
  private long lastTokenCacheCleanup;

  @Override
  public void run() {
   
    LOGGER.info("Starting expired delegation token remover thread, "
        + "tokenRemoverScanInterval=" + tokenRemoverScanInterval
        / (60 * 1000) + " min(s)");
    while (running) {
   
      try {
   
        long now = System.currentTimeMillis();
        if (lastMasterKeyUpdate + keyUpdateInterval < now) {
   
          try {
   
            rollMasterKeyExt();
            lastMasterKeyUpdate = now;
          } catch (IOException e) {
   
            LOGGER.error("Master key updating failed. "
                + StringUtils.stringifyException(e));
          }
        }
        if (lastTokenCacheCleanup + tokenRemoverScanInterval < now) {
   
          removeExpiredTokens();
          lastTokenCacheCleanup = now;
        }
        try {
   
          Thread.sleep(5000); // 5 seconds
        } catch (InterruptedException ie) {
   
          LOGGER
          .error("InterruptedException received for ExpiredTokenRemover thread "
              + ie);
        }
      } catch (Throwable t) {
   
        LOGGER.error("ExpiredTokenRemover thread received unexpected exception. "
                         + t, t);
        // Wait 5 seconds too in case of an exception, so we do not end up in busy waiting for
        // the solution for this exception
        try {
   
          Thread.sleep(5000); // 5 seconds
        } catch (InterruptedException ie) {
   
          LOGGER.error("InterruptedException received for ExpiredTokenRemover thread during " +
              "wait in exception sleep " + ie);
        }
      }
    }
  }
}

/**
 * Remove expired tokens. Replaces logic in {@link AbstractDelegationTokenSecretManager}
 * that cannot be reused due to private method access. Logic here can more efficiently
 * deal with external token store by only loading into memory the minimum data needed.
 */
protected void removeExpiredTokens() {
   
  long now = System.currentTimeMillis();
  Iterator<DelegationTokenIdentifier> i = tokenStore.getAllDelegationTokenIdentifiers()
      .iterator();
  while (i.hasNext()) {
   
    DelegationTokenIdentifier id = i.next();
    if (now > id.getMaxDate()) {
   
      this.tokenStore.removeToken(id); // no need to look at token info
    } else {
   
      // get token info to check renew date
      DelegationTokenInformation tokenInfo = tokenStore.getToken(id);
      if (tokenInfo != null) {
   
        if (now > tokenInfo.getRenewDate()) {
   
          this.tokenStore.removeToken(id);
        }
      }
    }
  }
}

  如上述代码所示,ExpiredTokenRemover 只有两个参数 lastMasterKeyUpdate 和 lastTokenCacheCleanup,
分别和 keyUpdateInterval 和 tokenRemoverScanInterval 配合起作用。其中:

  • keyUpdateInterval 是更新 hive.master_keys 表的时间间隔,lastMasterKeyUpdate 是记录上次更新的时间。master_keys 表里的 MASTER_KEY 是服务于生成 token 的,每个 HS2 维护一个,出于安全策略的考虑需要每天更新一次
  • tokenRemoverScanInterval 是更新清理过期 token 的时间间隔,lastTokenCacheCleanup 是记录上次清理的时间。

五、优化

  由于每个 HS2 和 HMS 都会做相同的逻辑,在集群规模比较大的情况下,该操作可以交给部分进程来进行(至少有一个就行)。
目前 Hive 本身没有提供直接关闭该清理线程的入口,所以短期考虑用以下方式实现:

  • 调整清理时间间隔参数 hive.cluster.delegation.token.gc-interval(会覆盖 tokenRemoverScanInterval 的值) 为 long 的最大值,间接关闭该功能

  后面考虑对保留清理逻辑的进程,控制其清理过期 token 的频率和时间段,避开业务高峰期。


  又 get 到一个知识点,下次见~

目录
相关文章
|
4月前
|
SQL 数据采集 数据挖掘
大数据行业应用之Hive数据分析航班线路相关的各项指标
大数据行业应用之Hive数据分析航班线路相关的各项指标
91 1
|
4月前
|
SQL 存储 大数据
【大数据技术Hadoop+Spark】Hive基础SQL语法DDL、DML、DQL讲解及演示(附SQL语句)
【大数据技术Hadoop+Spark】Hive基础SQL语法DDL、DML、DQL讲解及演示(附SQL语句)
70 0
|
6月前
|
SQL 分布式计算 大数据
黑马程序员-大数据入门到实战-分布式SQL计算 Hive 入门
黑马程序员-大数据入门到实战-分布式SQL计算 Hive 入门
64 0
|
6月前
|
SQL Java 大数据
Hive实战(03)-深入了解Hive JDBC:在大数据世界中实现数据交互
Hive实战(03)-深入了解Hive JDBC:在大数据世界中实现数据交互
165 1
|
4月前
|
SQL 分布式计算 数据库
【大数据技术Spark】Spark SQL操作Dataframe、读写MySQL、Hive数据库实战(附源码)
【大数据技术Spark】Spark SQL操作Dataframe、读写MySQL、Hive数据库实战(附源码)
82 0
|
4月前
|
SQL 存储 分布式计算
【大数据技术Hadoop+Spark】Hive数据仓库架构、优缺点、数据模型介绍(图文解释 超详细)
【大数据技术Hadoop+Spark】Hive数据仓库架构、优缺点、数据模型介绍(图文解释 超详细)
133 0
|
6月前
|
SQL 存储 大数据
黑马程序员-大数据入门到实战-分布式SQL计算 Hive 语法与概念
黑马程序员-大数据入门到实战-分布式SQL计算 Hive 语法与概念
70 0
|
6月前
|
SQL 前端开发 Java
大数据平台底层技术-JAVA篇-如何动态加载不同版本的 HIVE JDBC 驱动 - 一文读懂JAVA的类加载机制 1
大数据平台底层技术-JAVA篇-如何动态加载不同版本的 HIVE JDBC 驱动 - 一文读懂JAVA的类加载机制
|
2天前
|
SQL 分布式计算 Hadoop
利用Hive与Hadoop构建大数据仓库:从零到一
【4月更文挑战第7天】本文介绍了如何使用Apache Hive与Hadoop构建大数据仓库。Hadoop的HDFS和YARN提供分布式存储和资源管理,而Hive作为基于Hadoop的数据仓库系统,通过HiveQL简化大数据查询。构建过程包括设置Hadoop集群、安装配置Hive、数据导入与管理、查询分析以及ETL与调度。大数据仓库的应用场景包括海量数据存储、离线分析、数据服务化和数据湖构建,为企业决策和创新提供支持。
26 1
|
6月前
|
SQL Java 大数据
大数据平台底层技术-JAVA篇-如何动态加载不同版本的 HIVE JDBC 驱动 - 一文读懂JAVA的类加载机制 2
大数据平台底层技术-JAVA篇-如何动态加载不同版本的 HIVE JDBC 驱动 - 一文读懂JAVA的类加载机制