Skip to content

TIP

需求:使用Flume按天将日志数据存储到HDFS的对应目录中,并使用SQL按天统计每天的数据指标。

每天产生的JSON数据如下,

json
{
    "id": 86,
    "title": "数据结构和算法极速上手-java版",
    "coverImg": "https://file.aaa.net/video/2023/cover/86.png",
    "oldAmount": 99.00,
    "type": "video_info"
}
{
    "id":2,
    "name": "张三",
    "headImg": "https://file.ttt.net/user/2023/cover/2.png",
    "type": "user_info"
}

需求分析

  1. 使用Flume进行数据采集,按照天和类型进行存储,存储到HDFS的/moreType/日期/类型目录下。
  2. Flume的组件如下:exec source、channel可以选择基于文件或内存,sink选择hdfs sink。在hdfssink的path路径中使用%Y%m%d获取日期,将每天的日志数据采集到指定的HDFS目录中。
  3. 对按天采集的日志数据建立外部表,以支持多种计算引擎的使用。此外,由于离线计算的需求通常是按天计算的,在表中增加日期分区字段。
  4. 不再演示Flume采集数据的流程。

1.创建一个字段存储整个JSON数据

创建表,只有一个字段存储单条JSON数据。

sql
create external table ex_par_more_type (
    log string
) partitioned by (dt string, d_type string) 
 row format delimited 
 fields terminated by '\t'
 location '/moreType';

第二步是添加分区,以下操作每天都得做一次

sql
alter table ex_par_more_type add partition(dt='20231016',d_type='video_info') location '/moreType/20231016/video_info';
alter table ex_par_more_type add partition(dt='20231016',d_type='user_info') location '/moreType/20231016/user_info';

2.创建视图

创建一个视图,该视图用于查询之前创建的外部分区表。在查询时,视图会解析JSON数据中的字段,以便我们以后只需查询视图即可获取所需的字段信息,而无需编写任何代码。

sql
create view view_info_view as select 
get_json_object(log, '$.id') as id,
get_json_object(log, '$.title') as title,
get_json_object(log, '$.coverImg') as coverImg,
get_json_object(log, '$.oldAmount') as oldAmount,
dt
from ex_par_more_type where d_type='video_info'

注意,由于不同类型的数据,JSON结构可能是不同的,在实际应用过程中注意区分。

sql
create view user_info_view as select 
get_json_object(log, '$.id') as id,
get_json_object(log, '$.name') as name,
get_json_object(log, '$.headImg') as headImg,
dt
from ex_par_more_type where d_type='user_info'

查询时可指定日期进行查询

sql
select * from user_info_view where dt = '20231016';

TIP

get_json_object 是 Hive 中的一个内置函数,用于从 JSON 字符串中提取指定的键对应的值。它的语法如下:

sql
get_json_object(json_string, '$.key') -- json_string是json字符串,key是要提取的键

$.key 是一个 JSONPath 表达式,表示提取 JSON 对象中的 key 键的值。

3.编写脚本,定时添加分区

期flume每天都会采集新的数据上传到hdfs上面,所以我们需要每天都做一次添加分区的操作。编写一个脚本addPartition.sh代替人工操作:

shell
#!/bin/bash
# 每天凌晨1点定时添加当天日期的分区
if [ "a$1" = "a" ]
then
    dt=`date +%Y%m%d`
else
    dt=$1
fi
# 指定添加分区操作
hive -e "
alter table ex_par_more_type add if not exists partition(dt='${dt}',d_type='video_info') location '/moreType/${dt}/video_info';
alter table ex_par_more_type add if not exists partition(dt='${dt}',d_type='user_info') location '/moreType/${dt}/user_info';
"

TIP

如果指定的分区已存在,重复添加分区会报错,为了避免报错,需要使用if not exists

corntab定时任务

00 01 * * * root /bin/bash /data/soft/hivedata/addPartition.sh >> /data/soft/hivedata/addPartition.log