前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住给大家分享一下。点击跳转到网站:https://www.captainai.net/dongkelun
前言
接Zookeeper 安装配置 和 Hadoop HA 集群安装配置,本文继续总结 Hive 集群安装配置。其实之前的文章中已经总结过部分,但是不全面:
- Centos7 hive 单机模式安装配置 : 单机版元数据库初始化、Hive CLI 使用嵌入式 Metastore 模式连接 Hive 。
- Spark连接Hive(spark-shell和Eclipse两种方式):单机版独立 Metastore 服务启动 、Spark 通过独立的 HMS 服务 连接 Hive 。
- 通过数据库客户端界面工具DBeaver连接Hive: 单机版 HiveServer2 启动(使用嵌入式 Metastore)、DBeaver 通过 HiveServer2 JBDCUrl 地址连接Hive 。
前提
主机名修改、SSH互信、JDK安装等。
版本
Hive 3.1.3
安装包
https://archive.apache.org/dist/hive/hive-3.1.3/apache-hive-3.1.3-bin.tar.gz
安装 MySQL
在线安装 MySQL 服务器
前提:能连接外网
1 | wget https://dev.mysql.com/get/mysql80-community-release-el8-1.noarch.rpm |
离线安装 MySQL 服务器
如果所在节点不能连接外网,需要提前下载所有所需的 RPM 包(包括主程序和依赖),然后在目标机器上离线安装。以下是具体步骤:
在能联网的机器上下载所有依赖包
准备下载目录:1
mkdir -p /tmp/mysql-offline && cd /tmp/mysql-offline
下载 MySQL 官方仓库配置包(用于获取依赖列表):1
wget https://dev.mysql.com/get/mysql80-community-release-el8-1.noarch.rpm
安装仓库配置包(仅在下载机上临时安装,用于解析依赖):1
sudo rpm -ivh mysql80-community-release-el8-1.noarch.rpm
下载 MySQL 及所有依赖包(保存到本地,不安装):1
sudo yum install --downloadonly --downloaddir=. mysql-community-server
复制包到离线机器
将 /tmp/mysql-offline 目录下的所有 .rpm 文件 传输到离线安装的机器上(例如复制到 /opt/mysql-offline 目录)。
在离线机器上安装
1 | # 进入包目录 |
遇到问题:因为 /tmp/mysql-offline 包含了非必要的 mysql80-community-release-el8-1.noarch.rpm ,如果在离线机器上已经安装了 mysql80-community-release-el8-1.noarch.rpm ,那么执行 sudo rpm -ivh –nodeps *.rpm 时,会输出 package mysql80-community-release-el8-1.noarch is already installed ,然后就不安装其他包了。
那么解决方法有 3 个 :
- 1、 删除这个没必要的 rpm 包 :sudo rm -r mysql80-community-release-el8-1.noarch.rpm ,然后再 sudo rpm -ivh –nodeps *.rpm
- 2、先卸载该包: sudo rpm -e mysql80-community-release-el8-1.noarch ,然后再 sudo rpm -ivh –nodeps *.rpm
- 3、 逐个安装依赖包
1
2
3
4
5
6
7
8
9# 安装基础依赖包
sudo rpm -ivh --nodeps mysql-community-common-8.0.43-1.el8.x86_64.rpm
sudo rpm -ivh --nodeps mysql-community-client-plugins-8.0.43-1.el8.x86_64.rpm
sudo rpm -ivh --nodeps mysql-community-libs-8.0.43-1.el8.x86_64.rpm
sudo rpm -ivh --nodeps mysql-community-client-8.0.43-1.el8.x86_64.rpm
sudo rpm -ivh --nodeps mysql-community-icu-data-files-8.0.43-1.el8.x86_64.rpm
# 最后安装服务器包
sudo rpm -ivh --nodeps mysql-community-server-8.0.43-1.el8.x86_64.rpm
启动 MySQL 服务并设置开机自启
1 | # 启动服务 |
获取初始密码
MySQL 安装后会生成临时密码,查看方式:1
sudo grep 'temporary password' /var/log/mysqld.log
安全配置 MySQL
运行安全脚本进行初始化配置::1
sudo mysql_secure_installation
按照提示进行操作,主要包括:
- 输入初始密码
- 设置新密码(需包含大小写字母、数字和特殊字符)
- 移除匿名用户
- 禁止 root 远程登录
- 移除测试数据库
- 重新加载权限表
验证安装
登录 MySQL 测试是否安装成功:1
mysql -u root -p
输入设置的新密码,成功进入 MySQL 命令行则表示安装完成。
配置防火墙
如果需要远程访问 MySQL,需开放 3306 端口:1
2sudo firewall-cmd --zone=public --add-port=3306/tcp --permanent
sudo firewall-cmd --reload
创建远程连接用户
1 | CREATE USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'Root-123'; |
解压 Hive
1 | tar -zxvf apache-hive-3.1.3-bin.tar.gz -C /usr/local/ |
配置环境变量
1 | vi /etc/profile.d/hive.sh |
1 | export HIVE_HOME=/usr/local/hive |
1 | source /etc/profile |
配置 hive-site.xml
1 | vi /usr/local/hive/conf/hive-site.xml |
1 | <configuration> |
初始化元数据
1 | schematool -initSchema -dbType mysql |
1 | Metastore connection URL: jdbc:mysql://192.168.1.1:3306/hive_metadata?&createDatabaseIfNotExist=true&characterEncoding=UTF-8&useSSL=false |
这里会在 mysql 中创建一个 hive_metadata 的数据库,并在该库下初始化很多元数据表
Hive CLI
这个时候就可以用 hive 命令行连接了,之后再执行一些基本的 SQL 进行测试。
这里其实 Hive CLI 会通过读取 Hive 配置文件中的参数,建立与 Metastore 的通信连接,以获取元数据(如表结构、分区信息等),但是目前为止我们前面的配置并没有显示配置 Hive Metastore 的地址(通过 hive.metastore.uris 指定),也没有启动 Hive Metastore 服务。那么它是怎么实现的呢?
嵌入式 Metastore
如果未配置 hive.metastore.uris,Hive CLI 会默认采用嵌入式 Metastore 模式(Embedded Metastore Mode),而非连接独立的 Metastore 服务
独立 Metastore
若要使用独立的 Metastore 服务(推荐生产环境),只需在 hive-site.xml 中配置 hive.metastore.uris 并启动 Metastore 服务:
嵌入式 Metastore 模式存在明显缺陷,仅适合本地测试或临时操作,不适合生产环境
配置 Metastore 地址:
1 | <property> |
启动独立 Metastore 服务:
前台启动(便于查看日志,按 Ctrl+C 停止):1
hive --service metastore
后台启动(生产环境常用):1
2
3mkdir -p /var/log/hive
nohup hive --service metastore > /var/log/hive/hive-metastore.log 2>&1 &
nohup hive --service metastore --hiveconf hive.root.logger=INFO,console > /var/log/hive/hive-metastore.log 2>&1 &
查看日志无异常,并确认 9083 端口已启动
重启 Hive CLI,此时会连接到配置的独立 Metastore。
HiveServer2
HiveServer2 提供了一个 JDBC URL 供客户端连接,HiveServer2 底层依赖 Metastore 服务。
启动服务
前台启动(便于查看日志,按 Ctrl+C 停止)1
hive --service hiveserver2
后台启动(生产环境常用):1
nohup hive --service hiveserver2 > /var/log/hive/hiveserver2.log 2>&1 &
HiveServer2 使用嵌入式 Metastore
删除配置中 hive.metastore.uris ,这时启动的 HiveServer2 使用的是嵌入式 Metastore。这时默认的 10000 端口是正常启动的 。
HiveServer2 使用独立 Metastore 服务
配置中添加 hive.metastore.uris ,这时启动的 HiveServer2 使用的是配置文件中的独立 Metastore 服务,但是这时 10000 并没有正常启动。
这时 HiveServer2 日志并没有异常信息,只会定期的打印:
1
2Hive Session ID =……
Hive Session ID =……
Metastore 服务也不打印日志,这是因为我在上面的步骤中,没有配置 hive-log4j2.properties, 我们可以临时在命令行中添加日志配置:--hiveconf hive.root.logger=INFO,console,重启 Metastore 和 HiveServer2 :1
2hive --service metastore --hiveconf hive.root.logger=INFO,console
hive --service hiveserver2 --hiveconf hive.root.logger=INFO,console
然后就可以看到异常日志了:1
2
3
42025-10-23T14:39:31,302 WARN [main] metastore.RetryingMetaStoreClient: MetaStoreClient lost connection. Attempting to reconnect (1 of 1) after 1s. getCurrentNotificationEventId
org.apache.thrift.TApplicationException: Internal error processing get_current_notificationEventId
2025-10-23T14:39:32,324 WARN [pool-6-thread-1] metastore.RetryingMetaStoreClient: MetaStoreClient lost connection. Attempting to reconnect (1 of 1) after 1s. getTableObjectsByName
org.apache.thrift.transport.TTransportException: Cannot write to null outputStream
1 | 2025-10-23T14:39:32,306 ERROR [pool-6-thread-3] metastore.HiveMetaStore: Not authorized to make the get_current_notificationEventId call. You can try to disable metastore.metastore.event.db.notification.api.auth |
根据 Metastore 中的异常日志信息,修改配置,在 hive-site.xml 添加:
1 | <property> |
然后再重启 重启 Metastore 和 HiveServer2 :
在命令行中配置日志只是临时方法,正式生产上可以通过添加 hive-log4j2.properties ,下面是简单的配置示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16name=HiveSimpleLog
status=WARN
appender.console.type=Console
appender.console.name=console
appender.console.target=SYSTEM_OUT
appender.console.layout.type=PatternLayout
appender.console.layout.pattern=%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %c - %msg%n
rootLogger.level=INFO
rootLogger.appenderRefs=console
rootLogger.appenderRef.console.ref=console
#logger.hadoop.name=org.apache.hadoop
#logger.hadoop.level=WARN
连接 HiveServer2
通过 beeline 连接 。1
beeline -u jdbc:hive2://indata-192-168-1-1.indata.com:10000
异常解决
这个异常其实已经在之前的文章中讲过了。
异常:1
User: root is not allowed to impersonate anonymous
修改 core-site.xml ,添加:
1 | <property> |
然后再重启 Hadoop、Metastore、HiveServer2 就可以了。

Hive Metastore 高可用
配置
修改 hive-site.xml
1 | <property> |
启动
分别在 1、2 节点启动 Metastore
1 | hive --service metastore --hiveconf hive.root.logger=INFO,console |
验证高可用
首先重启 HiveServer2 ,然后通过 beeline 连接 HiveServer2 ,执行简单的 SQL,此时能正常查询 :
- 没有配置高可用:停掉 1 节点 Metastore ,再次查询,会报错:Connection refused
- 配置了高可用:停掉 1 节点 Metastore,再次查询是正常的,只有把其他节点所有 Metastore 停掉后才会报错 :Connection refused
原理说明
常规连接原理:
高可用原理:
这里参考引用:https://xie.infoq.cn/article/e49a62364e09e2f18cf38c43b
Hive Metastore 客户端始终使用第一个 URI 连接到 Metastore 服务器。如果 Metastore 服务器变得无法访问,则客户端从列表中随机选取一个 URI 并尝试与之建立连接。我们可以从 HiveServer2 日志验证:


可以看到 HiveServer2 启动时先连接的 2 节点 Metastore ,连接成功后关闭连接又连接的 1 节点 Metastore,也就是最开始实际使用的为 1 节点 Metastore ,然后把 1 节点 Metastore 手动关闭后,HiveServer2 会报异常,然后尝试连接所有的 Metastore 节点,直到有一个能连接成功,如果都不能连接成功则最终抛出异常 :Could not connect to meta store using any of the URIs provided.
另外,我们也可以观察 Metastore 的日志,我们在 beeline 里执行 sql 时,每次都是 1 节点 Metastore 打印日志,当把 1 节点 Metastore 停掉后 ,再次执行 sql 时 ,2 节点 Metastore 才打印日志。
HiveServer2 高可用
配置
修改 hive-site.xml , 添加:
1 | <property> |
启动
重启第一个节点的 HiveServer2 ,可以看到与 Zookeeper :相关的日志信息:
1 | INFO [main] thrift.ThriftCLIService: Starting ThriftBinaryCLIService on port 10000 with 5...500 worker threads |
另外在 Zookeeper 也可以看到对应的命名空间:
然后在第二个节点也启动 HiveServer2 ,同样在启动日志里可以看到成功连接 Zookeeper 的信息,此时再看 Zookeeper 对应的命名空间,会发现多了 2 节点 HiveServer2 的信息 。
连接 HiveServer2 高可用
HiveServer2 高可用对应的 JDBC URL 为:1
2
3
4# 不指定数据库名称,默认default
jdbc:hive2://indata-192-168-1-1.indata.com:2181,indata-192-168-1-2.indata.com:2181,indata-192-168-1-3.indata.com:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2
# 显示指定数据库名称
jdbc:hive2://indata-192-168-1-1.indata.com:2181,indata-192-168-1-2.indata.com:2181,indata-192-168-1-3.indata.com:2181/default;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2
通过 beeline 连接 。1
2
3beeline -u "jdbc:hive2://indata-192-168-1-1.indata.com:2181,indata-192-168-1-2.indata.com:2181,indata-192-168-1-3.indata.com:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2"
beeline -u "jdbc:hive2://indata-192-168-1-1.indata.com:2181,indata-192-168-1-2.indata.com:2181,indata-192-168-1-3.indata.com:2181/default;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2"
beeline -u "jdbc:hive2://indata-192-168-1-1.indata.com:2181,indata-192-168-1-2.indata.com:2181,indata-192-168-1-3.indata.com:2181/mydb;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2"
可以通过 SELECT current_database(); 验证当前数据库:
HiveServer2 HA 的原理
HiveServer2 HA 的原理主要是通过部署多个 HiveServer2 实例,并结合 ZooKeeper 实现服务发现与负载均衡,从而确保在部分实例出现故障时,系统仍能持续提供服务。以下是具体原理介绍:
- 服务注册:每个 HiveServer2 实例启动时,会将自己的地址(包括主机名和端口号等信息)注册到 ZooKeeper 的指定节点下。例如,在配置文件hive-site.xml中通过设置hive.server2.zookeeper.namespace等属性来指定 ZooKeeper 的命名空间和连接信息,使得 HiveServer2 能够正确地向 ZooKeeper 注册。
- 服务发现与负载均衡:客户端(如 JDBC、ODBC 客户端)连接 HiveServer2 时,不再直接指定某个固定的 HiveServer2 实例的地址,而是连接到 ZooKeeper。ZooKeeper 会从注册的 HiveServer2 实例中随机选择一个返回给客户端,客户端使用该地址连接对应的 HiveServer2 实例进行查询等操作,这样在一定程度上实现了负载均衡。
- 故障转移:当正在为客户端服务的 HiveServer2 实例发生故障时,由于 ZooKeeper 会持续监控各个 HiveServer2 实例的状态,它能够检测到该故障。不过,HiveServer2 本身并不支持自动的会话故障转移,即客户端会话会终止,需要客户端重新连接 ZooKeeper,获取新的可用 HiveServer2 实例地址并重新建立连接。
服务注册我们在上面已经验证过了,服务发现与负载均衡可以通过多次 beeline 连接 HiveServer2 HA JDBC URL,然后就会发现,有时会连接到 1 节点 10000端口的 HiveServer2 ,有时会连接到 2节点 10000端口的 HiveServer2 :
配置 beeline 默认连接地址
beeline 默认不会连接任何地址:
每次都通过 beeline -u 指定 HiveServer2 HA 连接地址比较麻烦,想给 beeline 配置默认连接地址为 HiveServer2 HA 连接地址 ,这样使用起来比较方便。查到有两个相关的配置:
1 | <property> |
但是在 hive-site.xml 添加后并没有生效,然后 查到一个配置文件 beeline-site.xml , 新建该配置文件,添加上面两个任何一个配置 , beeline 都会默认连接 HA 地址,但是需要用户名密码(实际只需要输入两次回车就行):

后来发现,其实只要有 beeline-site.xml 这个文件,即使内容为空,beeline 都会默认连接 HA 地址 。
然后通过博客:https://blog.csdn.net/caolijun1166/article/details/81705586,发现通过新建 beeline-hs2-connection.xml ,然后添加1
2
3
4
5
6
7
8
9
10
11<configuration>
<property>
<name>beeline.hs2.connection.user</name>
<value>root</value>
<description>根据实际情况修改,主要涉及 HDFS 目录权限问题</description>
</property>
<property>
<name>beeline.hs2.connection.password</name>
<value>password</value>
</property>
</configuration>
就不需要输入用户名密码了,另外和 beeline-site.xml 文件一样,只要有 beeline-hs2-connection.xml 即使内容为空,beeline 都会默认连接 HA 地址
完整配置
hive-site.xml 完整配置:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://192.168.1.1:3306/hive_metadata?&createDatabaseIfNotExist=true&characterEncoding=UTF-8&useSSL=false</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hive</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>Hive-123</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.cj.jdbc.Driver</value>
</property>
<property>
<name>datanucleus.schema.autoCreateAll</name>
<value>true</value>
</property>
<property>
<name>hive.server2.thrift.port</name>
<value>10000</value>
</property>
<property>
<name>hive.metastore.event.db.notification.api.auth</name>
<value>false</value>
<description>禁用权限校验</description>
</property>
<property>
<name>hive.metastore.uris</name>
<value>thrift://indata-192-168-1-1.indata.com:9083,thrift://indata-192-168-1-2.indata.com:9083</value>
<description>格式:thrift://host1:port1,thrift://host2:port2</description>
</property>
<property>
<name>hive.server2.support.dynamic.service.discovery</name>
<value>true</value>
<description>控制 HiveServer2(HS2)是否支持动态服务发现</description>
</property>
<property>
<name>hive.server2.zookeeper.namespace</name>
<value>hiveserver2</value>
<description>ZooKeeper中的命名空间</description>
</property>
<property>
<name>hive.zookeeper.quorum</name>
<value>indata-192-168-1-1.indata.com,indata-192-168-1-2.indata.com,indata-192-168-1-3.indata.com</value>
<description>ZooKeeper集群节点</description>
</property>
<property>
<name>hive.zookeeper.client.port</name>
<value>2181</value>
<description>ZooKeeper端口</description>
</property>
</configuration>