Hive与AWS及HCatalog的使用指南
1. Hive与AWS相关操作
在使用Hive与AWS的过程中,有多种操作和配置需要注意。
1.1 自定义启动脚本
使用自定义启动脚本的优势在于能更严格地控制其在工作流生命周期中的执行时间,但需要自行管理调用。另外,使用文件存储Hive初始化查询的一个附带好处是可以通过版本控制跟踪DDL的更改。不过,当元信息随着表和分区的增多而变大时,启动时间会变长,因此如果表或分区较多,不建议使用此方法。
1.2 MySQL转储到S3
另一种方法是在终止集群前备份元存储,并在下一个工作流开始时恢复。S3是在集群不使用时持久保存备份的好地方。需要注意的是,在EMR集群上运行的不同版本的Hive之间,元存储是不共享的。若要在不同Hive版本间共享元数据,需使用外部持久元存储。
1.3 HDFS和S3在EMR集群中的角色
HDFS和S3在EMR集群中有不同的角色,具体如下表所示:
| 存储类型 | 特点 | 使用建议 |
| ---- | ---- | ---- |
| HDFS | 由核心实例组节点的临时存储组成,集群终止后数据丢失 | 存储处理的中间结果 |
| S3 | 为EMR集群相关数据提供持久存储 | 存储集群的输入数据和最终处理结果 |
使用S3作为输入数据源会失去Hadoop数据本地化优化,若此优化对分析至关重要,可在处理前将“热”数据从S3导入HDFS。
1.4 将资源、配置和引导脚本上传到S3
应将所有引导脚本、配置脚本(如hive-site.xml和.hiverc)、资源(如需要放入分布式缓存的文件、UDF或流式JAR)等上传到S3。例如,可在.hiverc中添加以下内容:
ADD FILE s3n://example.hive.oreilly.com/files/my_file.txt;
ADD JAR s3n://example.hive.oreilly.com/jars/udfs.jar;
CREATE TEMPORARY FUNCTION my_count AS 'com.oreilly.hive.example.MyCount';
1.5 S3上的日志
Amazon EMR将日志文件保存到log-uri字段指向的S3位置。该字段可在elastic-mapreduce Ruby客户端安装目录的credentials.json文件中设置,也可在启动集群时使用–log-uri标志指定或覆盖。若未设置该字段,日志将无法在S3上获取。同时,若工作流配置为在作业出错时终止,设置log-uri可在集群终止后仍能在S3上获取日志,有助于调试,但需定期清除不必要的日志以节省存储成本。
1.6 现货实例
现货实例允许用户对未使用的亚马逊容量进行投标,以低于按需价格的费率获取实例。使用现货实例有以下两种情况:
- 所有实例组都使用现货实例:整个集群可能在工作流的任何阶段终止,导致中间数据丢失。若重复计算成本低,这可能不是严重问题;也可定期将中间数据持久化到S3,前提是作业能从这些快照重新开始。
- 仅任务实例组使用现货节点:若这些节点因不可用或现货价格上涨而被移除,工作流将继续使用主节点和核心节点,且不会丢失数据。节点重新加入集群后,可将MapReduce任务委派给它们,加快工作流。
使用elastic-mapreduce Ruby客户端订购现货实例的示例命令如下:
elastic-mapreduce --create --alive --hive-interactive \
--name "Test Spot Instances" \
--instance-group master --instance-type m1.large \
--instance-count 1 --instance-group core \
--instance-type m1.small --instance-count 2 --instance-group task \
--instance-type m1.small --instance-count 2 --bid-price 0.10
使用Java SDK启动类似集群的配置示例如下:
InstanceGroupConfig masterConfig = new InstanceGroupConfig()
.withInstanceCount(1)
.withInstanceRole("MASTER")
.withInstanceType("m1.large");
InstanceGroupConfig coreConfig = new InstanceGroupConfig()
.withInstanceCount(2)
.withInstanceRole("CORE")
.withInstanceType("m1.small");
InstanceGroupConfig taskConfig = new InstanceGroupConfig()
.withInstanceCount(2)
.withInstanceRole("TASK")
.withInstanceType("m1.small")
.withMarket("SPOT")
.withBidPrice("0.05");
需要注意的是,若依赖过多现货实例,作业时间可能不可预测或因TaskTrackers被移除而完全失败。
1.7 安全组
Hadoop JobTracker和NameNode用户界面分别在EMR主节点的9100和9101端口可访问,可使用ssh隧道或动态SOCKS代理查看。若要从客户端机器的浏览器查看,需通过AWS Web控制台修改Elastic MapReduce主安全组,添加新的自定义TCP规则,允许客户端机器IP地址在9100和9101端口的入站连接。
1.8 EMR与EC2和Apache Hive对比
与EMR相比,启动多个Amazon EC2节点并在自定义AMI上安装Hadoop和Hive能让用户更好地控制Hive和Hadoop的版本和配置,但Apache Hive版本可能不具备EMR的一些定制功能。例如,S3文件系统在Apache Hive上不完全支持,且减少亚马逊S3查询启动时间的优化仅在EMR Hive中可用,可通过在hive-site.xml中添加以下内容启用:
<property>
<name>hive.optimize.s3.query</name>
<value>true</value>
<description> Improves Hive query performance for Amazon S3 queries
by reducing their start up time </description>
</property>
或者在Hive CLI中运行以下命令:
set hive.optimize.s3.query=true;
另外,若分区存在于HDFS或S3的正确目录结构中,可使用以下命令恢复分区:
ALTER TABLE emr_table RECOVER PARTITIONS;
创建表的语句示例如下:
CREATE EXTERNAL TABLE emr_table(id INT, value STRING)
PARTITIONED BY (dt STRING)
LOCATION 's3n://example.hive.oreilly.com/tables/emr_table';
2. HCatalog介绍
HCatalog的出现是为了满足在Hadoop上使用其他工具的用户访问Hive元存储的需求。它具有以下特点:
- 提供MapReduce和Pig的连接器,使用户能读写Hive仓库中的数据。
- 提供命令行工具,让不使用Hive的用户可以使用Hive DDL语句操作元存储。
- 提供通知服务,使工作流工具(如Oozie)能在仓库中有新数据可用时得到通知。
HCatalog是一个独立于Hive的Apache项目,目前最新版本是HCatalog 0.4.0 - incubating,可与Hive 0.9、Hadoop 1.0和Pig 0.9.2配合使用。
3. MapReduce与HCatalog结合使用
3.1 读取数据
MapReduce使用Java类InputFormat读取输入数据,HCatalog提供HCatInputFormat,使MapReduce用户能读取Hive数据仓库中的数据。其操作步骤如下:
1. 创建InputJobInfo类,指定要读取的数据库、表和分区过滤器:
InputJobInfo inputInfo = InputJobInfo.create(dbName, inputTableName, filter);
其中,databaseName表示Hive数据库(或模式),若为null则使用默认数据库;tableName为要读取的表名,必须有效;filter为分区过滤器,格式为类似SQL的where子句,如“datestamp = ‘2012 - 05 - 26’”。需要注意的是,Hive v0.9.0及更早版本的ORM映射层存在一个bug,会导致包含>、>=、<或<=的过滤子句失败,可通过应用补丁HIVE - 2084.D2397.1.patch解决。
2. 将InputJobInfo实例传递给HCatInputFormat:
Job job = new Job(conf, "Example");
HCatInputFormat.setInput(job, inputInfo);
- 映射任务需指定HCatRecord作为值类型,示例如下:
public static class Map extends
Mapper<WritableComparable, HCatRecord, Text, Text> {
@Override
protected void map(
WritableComparable key,
HCatRecord value,
org.apache.hadoop.mapreduce.Mapper<WritableComparable,
HCatRecord, Text, HCatRecord>.Context context) {
...
}
}
HCatRecord提供简单的get和set接口,可按位置或名称请求记录。若不想读取输入中的所有列,可在作业配置时传递描述所需列的模式,示例如下:
HCatSchema baseSchema = HCatBaseInputFormat.getOutputSchema(context);
List<HCatFieldSchema> fields = new List<HCatFieldSchema>(2);
fields.add(baseSchema.get("user"));
fields.add(baseSchema.get("url"));
HCatBaseInputFormat.setOutputSchema(job, new HCatSchema(fields));
3.2 写入数据
写入数据时,需指定要写入的数据库和表,若写入分区表且只写一个分区,还需指定分区。操作步骤如下:
1. 创建OutputJobInfo实例:
OutputJobInfo outputInfo = OutputJobInfo.create(dbName, outputTableName, partitionValues);
其中,databaseName和tableName含义与读取数据时相同,partitionValues表示要创建的分区,若表未分区,该字段可留空。若要进行动态分区,分区列的值必须存在于数据中。
2. 将OutputJobInfo实例传递给HCatOutputFormat:
HCatOutputFormat.setOutput(job, outputInfo);
- 写入时,输出键类型不重要,值必须为HCatRecord,可从归约器或仅映射作业的映射任务中写入记录。
以下是一个完整的示例代码,用于从表rawevents中读取日期戳为20120531的分区,统计每个用户的事件数量,并将结果写入表cntd:
public class MRExample extends Configured implements Tool {
public static class Map extends
Mapper<WritableComparable, HCatRecord, Text, LongWritable> {
protected void map(WritableComparable key,
HCatRecord value,
Mapper<WritableComparable, HCatRecord,
Text, LongWritable>.Context context)
throws IOException, InterruptedException {
// Get our schema from the Job object.
HCatSchema schema = HCatBaseInputFormat.getOutputSchema(context);
// Read the user field
String user = value.get("user", schema);
context.write(new Text(user), new LongWritable(1));
}
}
public static class Reduce extends Reducer<Text, LongWritable,
WritableComparable, HCatRecord> {
protected void reduce(Text key, Iterable<LongWritable> values,
Reducer<Text, LongWritable,
WritableComparable, HCatRecord>.Context context)
throws IOException ,InterruptedException {
List<HCatFieldSchema> columns = new ArrayList<HCatFieldSchema>(2);
columns.add(new HCatFieldSchema("user", HCatFieldSchema.Type.STRING, ""));
columns.add(new HCatFieldSchema("cnt", HCatFieldSchema.Type.BIGINT, ""));
HCatSchema schema = new HCatSchema(columns);
long sum = 0;
Iterator<IntWritable> iter = values.iterator();
while (iter.hasNext()) sum += iter.next().getLong();
HCatRecord output = new DefaultHCatRecord(2);
record.set("user", schema, key.toString());
record.setLong("cnt", schema, sum);
context.write(null, record);
}
}
public int run(String[] args) throws Exception {
Job job = new Job(conf, "Example");
// Read the "rawevents" table, partition "20120531", in the default
// database
HCatInputFormat.setInput(job, InputJobInfo.create(null, "rawevents",
"datestamp='20120531'"));
job.setInputFormatClass(HCatInputFormat.class);
job.setJarByClass(MRExample.class);
job.setMapperClass(Map.class);
job.setReducerClass(Reduce.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(LongWritable.class);
job.setOutputKeyClass(WritableComparable.class);
job.setOutputValueClass(DefaultHCatRecord.class);
// Write into "cntd" table, partition "20120531", in the default database
HCatOutputFormat.setOutput(job, OutputJobInfo.create(null, "cntd", "ds=20120531"));
job.setOutputFormatClass(HCatOutputFormat.class);
return (job.waitForCompletion(true) ? 0 : 1);
}
public static void main(String[] args) throws Exception {
int exitCode = ToolRunner.run(new MRExample(), args);
System.exit(exitCode);
}
}
综上所述,通过合理使用Hive与AWS的相关功能以及HCatalog,能更高效地进行数据处理和分析。在实际应用中,需根据具体需求和场景选择合适的方法和配置。
Hive与AWS及HCatalog的使用指南
4. 操作总结与注意事项
4.1 Hive与AWS操作总结
以下是Hive与AWS操作的关键要点总结:
| 操作类型 | 关键要点 |
| ---- | ---- |
| 自定义启动脚本 | 可严格控制执行时间,但需自行管理调用,数据量大时启动时间长 |
| MySQL转储到S3 | 备份元存储,不同Hive版本不共享,需外部持久元存储 |
| HDFS和S3使用 | HDFS存中间结果,S3存输入和最终结果,S3使用可能失去数据本地化优化 |
| 资源上传到S3 | 上传脚本、配置和资源,方便后续Hadoop作业使用 |
| S3日志管理 | 设置log - uri保存日志,定期清理节省成本 |
| 现货实例使用 | 按需选择实例组,注意作业时间可能受影响 |
| 安全组配置 | 修改安全组规则,允许特定端口入站连接 |
| EMR与EC2对比 | EC2可自定义配置,但可能缺少EMR定制功能 |
4.2 HCatalog操作总结
HCatalog主要用于让其他工具访问Hive元存储,其操作总结如下:
-
读取数据
:创建InputJobInfo指定读取信息,使用HCatInputFormat读取,可按需指定列。
-
写入数据
:创建OutputJobInfo指定写入信息,使用HCatOutputFormat写入,支持动态分区。
5. 操作流程梳理
5.1 Hive与AWS操作流程
graph LR
A[选择操作类型] --> B{自定义启动脚本}
A --> C{MySQL转储到S3}
A --> D{资源上传到S3}
A --> E{日志管理}
A --> F{使用现货实例}
A --> G{安全组配置}
A --> H{选择EMR或EC2}
B --> B1[编写脚本并管理调用]
C --> C1[备份元存储到S3]
D --> D1[上传脚本、配置和资源]
E --> E1[设置log - uri]
E --> E2[定期清理日志]
F --> F1{选择实例组}
F1 --> F2[配置现货实例参数]
G --> G1[修改安全组规则]
H --> H1{选择EMR}
H --> H2{选择EC2}
H1 --> H11[使用EMR定制功能]
H2 --> H21[自定义安装配置]
5.2 HCatalog操作流程
graph LR
I[选择操作类型] --> J{读取数据}
I --> K{写入数据}
J --> J1[创建InputJobInfo]
J1 --> J2[使用HCatInputFormat读取]
J2 --> J3[按需指定列]
K --> K1[创建OutputJobInfo]
K1 --> K2[使用HCatOutputFormat写入]
K2 --> K3{是否动态分区}
K3 --> |是| K4[确保分区列在数据中]
K3 --> |否| K5[指定分区信息]
6. 常见问题与解决方案
6.1 Hive与AWS常见问题
- 问题 :自定义启动脚本启动时间过长。
- 解决方案 :减少表和分区数量,或考虑其他启动方式。
- 问题 :不同Hive版本无法共享元数据。
- 解决方案 :使用外部持久元存储。
- 问题 :S3使用失去数据本地化优化。
- 解决方案 :处理前将“热”数据从S3导入HDFS。
- 问题 :现货实例导致作业时间不可预测或失败。
- 解决方案 :减少现货实例使用,或定期保存中间数据。
6.2 HCatalog常见问题
- 问题 :Hive v0.9.0及更早版本过滤子句失败。
- 解决方案 :应用补丁HIVE - 2084.D2397.1.patch。
- 问题 :写入数据时分区错误。
- 解决方案 :确保分区列信息正确,动态分区时分区列在数据中。
7. 实际应用案例分析
假设一家电商公司需要对用户行为数据进行分析,以了解用户的购买习惯和偏好。以下是使用上述技术的实际应用案例:
7.1 数据存储与管理
- 使用S3存储原始用户行为数据,如用户浏览记录、购买记录等。
- 使用Hive创建外部表,关联S3上的数据,方便后续查询和分析。
CREATE EXTERNAL TABLE user_behavior(id INT, user_id INT, action_type STRING, product_id INT)
PARTITIONED BY (dt STRING)
LOCATION 's3n://example.hive.oreilly.com/tables/user_behavior';
7.2 数据处理与分析
- 使用HCatalog和MapReduce对数据进行处理,例如统计每个用户的购买次数。
public class UserBehaviorAnalysis extends Configured implements Tool {
public static class Map extends
Mapper<WritableComparable, HCatRecord, Text, LongWritable> {
protected void map(WritableComparable key,
HCatRecord value,
Mapper<WritableComparable, HCatRecord,
Text, LongWritable>.Context context)
throws IOException, InterruptedException {
HCatSchema schema = HCatBaseInputFormat.getOutputSchema(context);
String user_id = value.get("user_id", schema);
context.write(new Text(user_id), new LongWritable(1));
}
}
public static class Reduce extends Reducer<Text, LongWritable,
WritableComparable, HCatRecord> {
protected void reduce(Text key, Iterable<LongWritable> values,
Reducer<Text, LongWritable,
WritableComparable, HCatRecord>.Context context)
throws IOException ,InterruptedException {
List<HCatFieldSchema> columns = new ArrayList<HCatFieldSchema>(2);
columns.add(new HCatFieldSchema("user_id", HCatFieldSchema.Type.STRING, ""));
columns.add(new HCatFieldSchema("purchase_count", HCatFieldSchema.Type.BIGINT, ""));
HCatSchema schema = new HCatSchema(columns);
long sum = 0;
Iterator<LongWritable> iter = values.iterator();
while (iter.hasNext()) sum += iter.next().get();
HCatRecord output = new DefaultHCatRecord(2);
output.set("user_id", schema, key.toString());
output.setLong("purchase_count", schema, sum);
context.write(null, output);
}
}
public int run(String[] args) throws Exception {
Job job = new Job(conf, "UserBehaviorAnalysis");
HCatInputFormat.setInput(job, InputJobInfo.create(null, "user_behavior",
"dt='2024 - 01 - 01'"));
job.setInputFormatClass(HCatInputFormat.class);
job.setJarByClass(UserBehaviorAnalysis.class);
job.setMapperClass(Map.class);
job.setReducerClass(Reduce.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(LongWritable.class);
job.setOutputKeyClass(WritableComparable.class);
job.setOutputValueClass(DefaultHCatRecord.class);
HCatOutputFormat.setOutput(job, OutputJobInfo.create(null, "user_purchase_count", null));
job.setOutputFormatClass(HCatOutputFormat.class);
return (job.waitForCompletion(true) ? 0 : 1);
}
public static void main(String[] args) throws Exception {
int exitCode = ToolRunner.run(new UserBehaviorAnalysis(), args);
System.exit(exitCode);
}
}
7.3 结果存储与使用
将处理结果存储在S3上,方便后续进一步分析或可视化展示。
6. 总结与建议
通过合理使用Hive与AWS的各项功能以及HCatalog,能够高效完成数据的存储、处理和分析任务。在实际应用中,建议:
- 根据数据量和业务需求选择合适的存储方式,如HDFS和S3的搭配使用。
- 谨慎使用现货实例,避免作业时间不可控。
- 及时处理S3上的日志,节省存储成本。
- 利用HCatalog实现不同工具间的数据共享,提高工作效率。
总之,充分掌握这些技术和操作方法,能为数据处理和分析工作带来极大的便利和效率提升。
超级会员免费看
1248

被折叠的 条评论
为什么被折叠?



