• Hive 入门


    Hive 入门

    一、准备

    1. Java 安装

    Hive 是一个基于 Hadoop 的数据仓库,而 Hadoop 是基于 Java 开发的,所以我们需要安装 Java。

    yum install -y java-1.8.0-openjdk-devel
    
    [root@iZuf6c82diwquwsq69eqejZ ~]# java -version
    openjdk version "1.8.0_292"
    OpenJDK Runtime Environment (build 1.8.0_292-b10)
    OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)
    

    2. Hadoop 安装

    Hadoop 是分布式文件存储系统,各个机器之间需要开启免密登录。为方便操作,这里我直接用 root 权限。如果是单机,就是自己免密登录自己,需要把生成的 id_rsa.pub 放到 authorized_keys 里面。

    ssh-keygen -t rsa
    

    我这里以三台机器为例,已经可以互相免密登录了。

    139.196.112.183  hadoop-master
    81.68.114.173    hadoop-slave1
    47.102.144.35    hadoop-slave2
    

    下载 Hadoop,实例为目前最新版本。(下载网址:https://hadoop.apache.org/releases.html)

    wget https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/hadoop-3.2.2/hadoop-3.2.2.tar.gz
    

    解压出来,我这里解压到当前目录。

    tar -zxvf hadoop-3.2.2.tar.gz
    
    [root@iZuf6c82diwquwsq69eqejZ hadoop]# pwd
    /work/docker/hadoop
    

    修改 hadoop-env.sh 文件,添加 JAVE_HOME。

    export JAVA_HOME=/usr
    

    验证 Hadoop 是否安装成功。

    [root@iZuf6c82diwquwsq69eqejZ hadoop]# /work/docker/hadoop/hadoop-3.2.2/bin/hadoop version
    Hadoop 3.2.2
    Source code repository Unknown -r 7a3bc90b05f257c8ace2f76d74264906f0f7a932
    Compiled by hexiaoqiao on 2021-01-03T09:26Z
    Compiled with protoc 2.5.0
    From source with checksum 5a8f564f46624254b27f6a33126ff4
    This command was run using /work/docker/hadoop/hadoop-3.2.2/share/hadoop/common/hadoop-common-3.2.2.jar
    

    接着在三台机器上,修改四个 xml 文件。

    # core-site.xml 文件,设置 hadoop 临时目录和 master。
    <configuration>
        <property>
            <name>hadoop.tmp.dir</name>
            <value>/work/docker/hadoop/tmp</value>
        </property>
        <property>
            <name>fs.defaultFS</name>
            <value>hdfs://hadoop-master:9000</value>
        </property>
    </configuration>
    
    # hdfs-site.xml 文件,设置 namenode 目录、datanode 目录和备份数。
    <configuration>
        <property>
            <name>dfs.name.dir</name>
            <value>/work/docker/hadoop/hdfs/name</value>
        </property>
        <property>
            <name>dfs.data.dir</name>
            <value>/work/docker/hadoop/hdfs/data</value>
        </property>
        <property>
            <name>dfs.replication</name>
            <value>2</value>
        </property>
    </configuration>
    
    # mapred-site.xml 文件,使用 yarn 集群来实现资源分配。
    <configuration>
        <property>
            <name>mapreduce.framework.name</name>
            <value>yarn</value>
        </property>
    </configuration>
    
    # yarn-site.xml 文件,设置 ResourceManager 对客户端暴露的地址,mapreduce_shuffle 为 NodeManager 上运行的附属服务,支持运行 MapReduce 程序。
    <configuration>
        <property>
            <name>yarn.resourcemanager.hostname</name>
            <value>hadoop-master</value>
        </property>
        <property>
            <name>yarn.nodemanager.aux-services</name>
            <value>mapreduce_shuffle</value>
        </property>
    </configuration>
    

    在 workers 文件中,列出所有节点的主机名或者 IP。

    hadoop-master
    hadoop-slave1
    hadoop-slave2
    

    分别在 sbin/start-dfs.sh, sbin/stop-dfs.sh 文件顶部添加如下配置:

    HDFS_DATANODE_USER=root
    HDFS_DATANODE_SECURE_USER=hdfs
    HDFS_NAMENODE_USER=root
    HDFS_SECONDARYNAMENODE_USER=root
    

    分别在 sbin/start-yarn.sh, sbin/stop-yarn.sh 文件顶部添加如下配置:

    YARN_RESOURCEMANAGER_USER=root
    HDFS_DATANODE_SECURE_USER=yarn
    YARN_NODEMANAGER_USER=root
    

    格式化 hdfs

    /work/docker/hadoop/hadoop-3.2.2/bin/hdfs namenode -format
    

    全部启动

    /work/docker/hadoop/hadoop-3.2.2/sbin/start-all.sh 
    

    注意:以上操作都是在 master 进行,master 的 hosts 需要填内网 IP。

    # master
    [root@iZuf6c82diwquwsq69eqejZ hadoop]# jps
    1241264 DataNode
    1241079 NameNode
    1242647 Jps
    1241737 ResourceManager
    1241902 NodeManager
    1241484 SecondaryNameNode
    
    # slave1
    [root@VM-0-6-centos hadoop]# jps
    10724 Jps
    10519 NodeManager
    10415 DataNode
    
    # slave2
    [root@iZuf65lasa7rugxfvzmywrZ hadoop]# jps
    550760 Jps
    550524 DataNode
    550638 NodeManager
    

    image

    image

    • NameNode

      在 master 上启动,负责调度。 当上传文件时,NameNode 会将文件分块并且分配到集群的 DataNode 节点上。NameNode 主要是用来保存 HDFS 的元数据信息,比如命名空间、块信息、节点信息等。当它运行的时候,这些信息是存在内存中的,也可以持久化到磁盘上。NameNode 启动的时候,会合并操作日志文件(edit logs)到镜像文件(fsimage)中,并且读取镜像文件。

    • SecondaryNameNode

      只有在 NameNode 重启的时候,操作日志文件才会合并到镜像文件中,而 NameNode 是很少重启的,所以当 NameNode 运行了很长时间后,操作日志文件就会变得很大。这样如果 NameNode 挂了,重启将异常缓慢,并且会丢失内存中未来得及写入操作日志文件的数据。因此 SecondaryNameNode 应运而生,它会定期地获取 edit logs,并更新到自己的 fsimage 上,然后 cp 到 NameNode 中。如此 NameNode 下次重启时就会使用新的 fsimage 文件,减少重启时间。因此 SecondaryNameNode 最好单独放在一台配置和 NameNode 所在机器差不多的机器上。指定 SecondaryNameNode 需在 hdfs-site.xml 文件中配置:

      <property>
      	<name>dfs.secondary.http.address</name>
      	<value>hadoop-slave2:50090</value>
      </property>
      

      注意:如果用的是云服务器,在 hadoop-slave2 机器上,这里得用内网 IP。

    • DataNode

      它是文件系统的工作节点,负责存储数据,并且定期地向 NameNode 发送它们所存储的块的列表。当 DataNode 有写操作的时候,会跟 NameNode 通信,NameNode 会将元数据信息写入 edit logs。

    • NodeManager

      是 YARN 集群每个节点上的代理,它管理 Hadoop 集群中单个计算节点。功能包括与 ResourceManager 保持通信,管理 Container(Container 是 YARN 中资源的抽象,它封装了某个节点上一定量的资源)的生命周期、监控每个 Container 的资源使用(内存、CPU等)情况、追踪节点健康状况、管理日志和不同应用程序用到的附属服务等。

    • ResourceManager

      负责 YARN 集群中所有资源的统一管理和分配,它接收来自各个节点(NodeManager)的资源汇报信息,并把这些信息按照一定的策略分配给各个应用程序。
      更多关于 Yarn 的资料:https://zhuanlan.zhihu.com/p/54192454

    3. Hive 安装

    因为我们的 Hadoop 版本是 3.2.2,所以 Hive 要下载与之匹配的 3.1.2 版本。下载地址:http://www.apache.org/dyn/closer.cgi/hive/

    http://mirrors.tuna.tsinghua.edu.cn/apache/hive/hive-3.1.2/apache-hive-3.1.2-bin.tar.gz
    

    解压到当前目录:

    tar -zxvf apache-hive-3.1.2-bin.tar.gz
    
    [root@iZuf6c82diwquwsq69eqejZ hive]# pwd
    /work/docker/hive
    

    在 conf 目录下新增 hive-env.sh 配置文件并设置 Hadoop 环境。

    HADOOP_HOME=/work/docker/hadoop/hadoop-3.2.2
    

    修改 hive-site.xml 配置文件:

    cp hive-default.xml.template hive-site.xml
    
    # 设置 Hive 临时文件目录
    <property>
    	<name>system:java.io.tmpdir</name>
    	<value>/work/docker/hive/tmp</value>
    </property>
    
    # 修改文件中所有的 ${system:user.name} 为 ${user.name}
    # 如下所示
    ${system:java.io.tmpdir}/${user.name}
    
    # 设置 metastore 为 MySQL
    <property>
      <name>javax.jdo.option.ConnectionURL</name>
      <value>jdbc:mysql://139.224.**.**:3306/hive?createDatabaseIfNotExist=true</value>
    </property>
    
    <property>
      <name>javax.jdo.option.ConnectionDriverName</name>
      <value>com.mysql.cj.jdbc.Driver</value>
    </property>
    
    <property>
      <name>javax.jdo.option.ConnectionUserName</name>
      <value>root</value>
    </property>
    
    <property>
      <name>javax.jdo.option.ConnectionPassword</name>
      <value>password</value>
    </property>
    

    下载对应版本的 MySQL 驱动,下载地址:https://downloads.mysql.com/archives/c-j/

    wget https://downloads.mysql.com/archives/get/p/3/file/mysql-connector-java-8.0.22.tar.gz
    

    解压出来复制到 lib 目录下:

    cp mysql-connector-java-8.0.22.jar /work/docker/hive/apache-hive-3.1.2-bin/lib
    

    注意: 3.2.2 版本的 Hadoop 和 3.1.2 版本的 Hive 有一个坑,两者的 guava-19.0.jar 版本不一样,启动会报错。我们需要把低版本的删掉,高版本的 cp 过来。

    rm -rf /work/docker/hive/apache-hive-3.1.2-bin/lib/guava-19.0.jar
    cp /work/docker/hadoop/hadoop-3.2.2/share/hadoop/common/lib/guava-27.0-jre.jar /work/docker/hive/apache-hive-3.1.2-bin/lib
    

    初始化 MySQL 数据库:

    /work/docker/hive/apache-hive-3.1.2-bin/bin/schematool -dbType mysql -initSchema
    

    注意: 这里还有一个坑,初始化的时候会报错:

    Exception in thread "main" java.lang.RuntimeException: com.ctc.wstx.exc.WstxParsingException: Illegal character entity: expansion character (code 0x8
     at [row,col,system-id]: [3219,96,"file:/work/docker/hive/apache-hive-3.1.2-bin/conf/hive-site.xml"]
    	at org.apache.hadoop.conf.Configuration.loadResource(Configuration.java:3040)
    	at org.apache.hadoop.conf.Configuration.loadResources(Configuration.java:2989)
    	at org.apache.hadoop.conf.Configuration.loadProps(Configuration.java:2864)
    	at org.apache.hadoop.conf.Configuration.addResourceObject(Configuration.java:1012)
    	at org.apache.hadoop.conf.Configuration.addResource(Configuration.java:917)
    	at org.apache.hadoop.hive.conf.HiveConf.initialize(HiveConf.java:5151)
    	at org.apache.hadoop.hive.conf.HiveConf.<init>(HiveConf.java:5104)
    	at org.apache.hive.beeline.HiveSchemaTool.<init>(HiveSchemaTool.java:96)
    	at org.apache.hive.beeline.HiveSchemaTool.main(HiveSchemaTool.java:1473)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.lang.reflect.Method.invoke(Method.java:498)
    	at org.apache.hadoop.util.RunJar.run(RunJar.java:323)
    	at org.apache.hadoop.util.RunJar.main(RunJar.java:236)
    Caused by: com.ctc.wstx.exc.WstxParsingException: Illegal character entity: expansion character (code 0x8
     at [row,col,system-id]: [3219,96,"file:/work/docker/hive/apache-hive-3.1.2-bin/conf/hive-site.xml"]
    	at com.ctc.wstx.sr.StreamScanner.constructWfcException(StreamScanner.java:621)
    	at com.ctc.wstx.sr.StreamScanner.throwParseError(StreamScanner.java:491)
    	at com.ctc.wstx.sr.StreamScanner.reportIllegalChar(StreamScanner.java:2456)
    	at com.ctc.wstx.sr.StreamScanner.validateChar(StreamScanner.java:2403)
    	at com.ctc.wstx.sr.StreamScanner.resolveCharEnt(StreamScanner.java:2369)
    	at com.ctc.wstx.sr.StreamScanner.fullyResolveEntity(StreamScanner.java:1515)
    	at com.ctc.wstx.sr.BasicStreamReader.nextFromTree(BasicStreamReader.java:2828)
    	at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1123)
    	at org.apache.hadoop.conf.Configuration$Parser.parseNext(Configuration.java:3336)
    	at org.apache.hadoop.conf.Configuration$Parser.parse(Configuration.java:3130)
    	at org.apache.hadoop.conf.Configuration.loadResource(Configuration.java:3023)
    	... 14 more
    

    我们只需要删掉 hive-site.xml 文件中,报错的那一行就行了。(这里我把整个 description 删掉了)

    3218     <description>
    3219       Ensures commands with OVERWRITE (such as INSERT OVERWRITE) acquire Exclusive locks for&#8;transactional tables.  This ensures that inserts (w/o overwrite) running concurrently
    3220       are not hidden by the INSERT OVERWRITE.
    3221     </description>
    

    再次初始化数据库,成功。至此,Hive 已经安装完毕。

    二、实战

    有这样一个业务场景,用户给主播刷礼物,然后主播查看每天的礼物报表。

    如此经典的情形,我们可以在服务端按照一定的格式打点,然后推送到 HDFS,再由 Hive 读取。这里有个很重要的概念,就是分区,在 HDFS 里面,分区体现在多个目录 。Hive 里面,分区体现在创表的时候的 PARTITIONED BY 语句。

    先在 Hadoop 里面创建好对应的目录:

    ./hadoop fs -mkdir -p /dclett/tv_gift
    
    [root@iZuf6c82diwquwsq69eqejZ bin]# ./hadoop fs -ls /dclett
    Found 1 items
    drwxr-xr-x   - root supergroup          0 2021-05-05 17:31 /dclett/tv_gift
    

    打点日志文件:

    # /work/dclett/tv_gift/210505/gift.log
    1,Dick,1001,17,101,apple,10,1620207298
    2,Erick,1001,17,102,banana,12,1620207345
    3,Alicia,1002,18,103,lipstick,1,1620207394
    
    # /work/dclett/tv_gift/210506/gift.log
    4,Dick,1002,18,104,candy,99,1620293698
    5,Alicia,1002,18,105,donut,99,1620293758
    
    [root@iZuf6c82diwquwsq69eqejZ dclett]# tree
    .
    └── tv_gift
        ├── 210505
        │   └── gift.log
        └── 210506
            └── gift.log
    

    分别将两天的日志文件推送到 HDFS:

    ./hadoop fs -mkdir /dclett/tv_gift/dt=210505; ./hadoop fs -put -f /work/dclett/tv_gift/210505/gift.log /dclett/tv_gift/dt=210505
    ./hadoop fs -mkdir /dclett/tv_gift/dt=210506; ./hadoop fs -put -f /work/dclett/tv_gift/210506/gift.log /dclett/tv_gift/dt=210506
    
    [root@iZuf6c82diwquwsq69eqejZ bin]# ./hadoop fs -ls /dclett/tv_gift
    Found 2 items
    drwxr-xr-x   - root supergroup          0 2021-05-05 17:47 /dclett/tv_gift/dt=210505
    drwxr-xr-x   - root supergroup          0 2021-05-05 17:48 /dclett/tv_gift/dt=210506
    

    创建 Hive 数据库和表(使用 dt 字段作为分区):

    create database dclett;
    use dclett;
    
    create table tv_gift(
    id int,
    name string,
    room_id int,
    anchor_id int,
    goods_id int,
    goods_name string,
    goods_num int,
    create_time int
    )
    PARTITIONED BY (
      `dt` string)
    row format delimited fields terminated by ','
    location 'hdfs://hadoop-master:9000/dclett/tv_gift';
    

    如此一来,貌似已经大功告成了。然而当我 select 的时候,却发现没有数据。

    hive> select * from tv_gift;
    OK
    Time taken: 0.489 seconds
    

    难道分区没有成功?

    hive> show partitions tv_gift;
    OK
    Time taken: 0.447 seconds
    

    可以说是分区没有成功,因为我们还少了一步操作:将分区信息写入 metastore。

    hive> msck repair table tv_gift;
    OK
    Partitions not in metastore:	tv_gift:dt=210505	tv_gift:dt=210506
    Repair: Added partition to metastore tv_gift:dt=210505
    Repair: Added partition to metastore tv_gift:dt=210506
    Time taken: 0.672 seconds, Fetched: 3 row(s)
    
    hive> show partitions tv_gift;
    OK
    dt=210505
    dt=210506
    Time taken: 0.739 seconds, Fetched: 2 row(s)
    

    MySQL 查看分区信息:

    mysql> select * from PARTITIONS;
    +---------+-------------+------------------+-----------+-------+--------+
    | PART_ID | CREATE_TIME | LAST_ACCESS_TIME | PART_NAME | SD_ID | TBL_ID |
    +---------+-------------+------------------+-----------+-------+--------+
    |       3 |  1620209674 |                0 | dt=210505 |    26 |     23 |
    |       4 |  1620209674 |                0 | dt=210506 |    27 |     23 |
    +---------+-------------+------------------+-----------+-------+--------+
    2 rows in set (0.00 sec)
    

    Hive 中现在有数据了:

    hive> select * from tv_gift;
    OK
    1	Dick	1001	17	101	apple	10	1620207298	210505
    2	Erick	1001	17	102	banana	12	1620207345	210505
    3	Alicia	1002	18	103	lipstick	1	1620207394	210505
    4	Dick	1002	18	104	candy	99	1620293698	210506
    5	Alicia	1002	18	105	donut	99	1620293758	210506
    Time taken: 0.503 seconds, Fetched: 5 row(s)
    

    如此才是大功告成,记得每次 put 新分区的时候在 Hive 执行下 msck repair table TableName 命令。

  • 相关阅读:
    ExtAspNet下通过文档路径实现文档的下载
    ExtjS学习--------Ext.define定义类
    【C语言天天练(二三)】errno变量
    Linux 内核kobject 层次, kset, 和子系统
    Linux 内核释放函数和 kobject 类型
    Linux 内核引用计数的操作
    Linux 内核 kobject 初始化
    Linux 内核 嵌入的 kobjects
    Kobjects, Ksets 和 Subsystems
    Kobjects, Ksets 和 Subsystems
  • 原文地址:https://www.cnblogs.com/74percent/p/14732376.html
Copyright © 2020-2023  润新知