返回介绍

12.1 使用 Hive

发布于 2025-04-22 19:57:21 字数 8318 浏览 0 评论 0 收藏

上一章使用了 MapReduce API 来分析存储在 HDFS 中的数据。虽然用 MapReduce API 来统计单词出现频率是个比较简单的任务,但是复杂的分析任务就不适合使用 MapReduce 模型了,这会降低开发效率。为了解决这个难题,Facebook 开发了 Hive 来与 Hadoop 以更具声明式、类 SQL 的方式交互。Hive 提供了一个名为 HiveQL 的语言用以分析存储在 HDFS 中的数据,因为它类似 SQL,所以非常容易学习。在底层,HiveQL 查询会被转换成基于 MapReduce API 的多个 Job。目前 Hive 是 Apache 上的顶级项目,但 Facebook 依然还在全力投入开发。

关于 Hive 更深入的介绍超出了本书的范围。它的基本编程模型是创建一个 Hive 表模式用来对 HDFS 中存储的数据提供结构。接着 HiveQL 查询会在 Hive 引擎中解析,并把它们转换成 MapReduce Job 以执行查询。HiveQL 语句可以通过命令行提交给 Hive 引擎,也可以通过名为 Hive 服务器的组件提交给引擎,这个组件提供了通过 JDBC、ODBC 或 Thrift 来进行访问功能。关于安装、运行以及使用 Hive 与 HiveQL 的更多详细介绍,可参考项目网站( http://hive.apache.org/ )以及《 Programming Hive 》(O’Reilly 出版)一书。

如同 MapReduce Job 一样,Spring for Apache Hadoop 的目标是简化 Hive 编程,不依赖于命令行工具来开发和运行 Hive 应用程序。取而代之,Spring for Apache Hadoop 连接 Hive 服务器(可选择内嵌方式)、创建 Hive Thrift 客户端,并通过 Hive JDBC 驱动来使用 Spring 丰富的 JDBC 支持(JdbcTemplate),进而简化 Java 应用程序的编写过程。

12.1.1 Hello World

为了介绍 Hive 的使用方式,这个小节将使用 Hive 命令行来对 UNIX passwd 文件执行简单的分析,目标是建立一个特定 Shell(例如 bash 或 sh)使用者数量的报表。可从 Hive( http://hive.apache.org/ )网站下载并安装 Hive,安装完 Hive 的发布版之后,需将它的 bin 目录加入到你的路径中。现在如示例 12-1 所示,可以启动 Hive 命令行控制台并执行一些 HiveQL 命令。

示例 12-1 在 Hive 命令行界面中分析 passwd 文件

P196

也可以将 HiveQL 命令放到文件中并在命令行执行它,如示例 12-2 所示。

示例 12-2 在命令行执行 Hive

P197a

Hive 命令行会将命令直接传给 Hive 引擎。Hive 也支持变量替换,脚本中可使用符号${hiveconf:varName}来替换在命令行中通过-hiveconfg varName = varValue 设置的变量。如果不使用命令行与 Hive 交互,就需要通过 Thrift 客户端或者 JDBC 连接到 Hive 服务器。下一个小节将介绍如何在命令行中启动 Hive 服务器,以及如何在 Java 应用程序中启动内嵌的服务器。

12.1.2 运行 Hive 服务器

在生产环境中,最常见的场景是将 Hive 服务器作为独立的服务器进程来运行 - 可能在 HAProxy 后面有多个 Hive 服务器 - 从而避免处理大量并发客户端连接所带来的问题 [1]

如果想把示例应用程序运行在独立的服务器中,可使用下面的命令来启动 Hive:

P197b

另一个对开发期很实用而且可免于运行其他服务器的方法是在同一个运行 Hive 客户端应用程序的 Java 进程中启动 Hive 服务。通过 Hadoop 命名空间只需一行配置即可嵌入 Hive 服务器,如示例 12-3 所示。

示例 12-3 使用默认配置项创建 Hive 服务器

P178

在默认配置下,主机名称为 localhost,端口为 10000,可以使用 host 与 port 属性来更改这些值。也可以通过 properties-location 引用属性文件或在<hive-server/>XML 元素中内联属性来对 Hive 服务器进行其他的配置。当应用上下文创建时,Hive 服务器会自动启动。如果不想 Hive 服务器自动启动的话,可以设置 auto-startup 元素为 false。最后,可以引用特定的 Hadoop 配置对象,创建多个连接不同 Hadoop 集群的 Hive 服务器。这些配置方式如示例 12-4 所示。

示例 12-4 创建与配置 Hive 服务器

P198a

hadoop.properties 和 hive.properties 文件是从类路径加载,它们组合起来的值如示例 12-5 所示。可以使用属性文件 hive-server.properties 来配置这个服务器,这些值和放在 hive-site.xml 里面的值一样。

示例 12-5 配置简单 Hive 应用程序的属性

P198b

12.1.3 使用 Hive Thrift 客户端

Hadoop 命名空间可用来创建 Thrift 客户端,如示例 12-6 所示。

示例 12-6 创建并配置 Hive Thrift 客户端

P179

这个命名空间会创建一个 HiveClientFactory 类的实例。调用 HiveClientFactory 的 getHiveClient 方法会返回一个新的 HiveClient 实例。这是 Spring 提供的一种便捷方式,因为 HiveClient 不是线程安全的类,因此在多线程共享的方法中必须要创建新的实例。通过 XML 命名空间,可以对 HiveClient 设置的参数还包括连接的超时时间以及当客户端建立连接时需要执行的一组脚本。为了使用 HiveClient,要创建 HivePasswordRepository 类来执行前一节使用的 password-analysis.hql 脚本,然后对 passwords 表进行查询。在之前的 Hive 服务器配置中加入<context:component-scan/>元素,即可扫描类路径找出带有 Spring 通用 @Repository 注解的类进而自动把 HivePasswordRepository 类注册到容器中,如示例 12-7 所示。

示例 12-7 在数据访问层使用 Thrift HiveClient

P199

这个示例应用程序的代码位于./hadoop/hive。参考示例目录中的 readme 文件可了解更多运行这个示例应用程序的信息。示例应用程序的驱动会调用 HivePasswordRepository 的 processPasswordFile 方法,接着调用它的 count 方法,对于我们的结果集所返回的值为 41。这个示例的错误处理方式是开发数据访问层的最佳实践,它避免了将已检查型异常抛给调用代码。

HiveTemplate 帮助类为简化编程式 Hive 开发提供了众多的好处。它会将 HiveClient 的检查型异常和错误转换成 Spring 便捷的 DAO 异常体系,这意味着调用代码不需要知道 Hive 细节。HiveClient 也不是线程安全的,因此同其他 Spring 模板类类似,HiveTemplate 会对底层资源提供线程安全的访问,因此不需要处理复杂的 HiveClient API,只需将精力集中在执行 HSQL 和获取结果集上。为创建 HiveTemplate,要使用 XML 命名空间以及一个可选的 HiveClientFactory 引用。示例 12-8 是新 PasswordRepository 实现的最小配置,这个实现使用了 HiveTemplate。

示例 12-8 配置 HiveTemplate

P200a

在<hive-template/>XML 命名空间中,可以使用 hive-client-factory-ref 元素通过名称显式地引用 HiveClientFactory。借助于 HiveTemplate 使得实现 HiveTemplatePasswordRepository 类更为容易,如示例 12-9 所示。

示例 12-9 借助 HiveTemplate 实现 HiveTemplatePasswordRepository

P200b

注意,HiveTemplate 类实现了 HiveOperations 接口。这是 Spring 模板类通用的实现方式,因为接口很容易模拟(mock)或提供存根(stub)实现,所以便于进行单元测试。借助 Spring 的 Resource 抽象,HiveTemplate 的查询方法允许将脚本地址的引用传递进来,这具有非常大的灵活性,可以从类路径、文件或 HTTP 加载 InputStream。这个查询方法的第二个参数用来替换脚本变量的值。HiveTemplate 也提供了一个很便利的回调方法,它会传递给你一个托管的 HiveClient 实例。类似于 Spring 中的其他模板类,如果这些便利的方法不能满足需求,则可以通过回调使用底层的 API 了,不过依然能够从模板的异常转换以及资源管理等特性中收益。

Spring for Apache Hadoop 还提供了一个类似于 JobRunner 的 HiveRunner 帮助类,可在运行 HiveQL 脚本之前和之后执行 HDFS 脚本操作。可以使用 XML 命名空间元素<hive-runner/>来配置这个 Runner。

12.1.4 使用 Hive JDBC 客户端

通过 JDBC 对 Hive 的支持,可以使用熟悉的 Spring JdbcTemplate 来与 Hive 交互。Hive 提供了 HiveDriver 类,它可以传入 Spring 的 SimpleDriverDataSource,如示例 12-10 所示。

示例 12-10 创建和配置基于 Hive JDBC 的访问

P201

SimpleDriverDataSource 提供标准 JDBC DataSource 接口的简单实现,它需要一个 java.sql.Driver 实现。每当 DataSource 的 getConnection 方法被调用时,它都会返回一个新的连接。这对大部分的 Hive JDBC 应用程序已经足够了,因为与执行 Hive 操作所耗费的时间长度相比,建立连接的开销已经很小了。如果需要连接池,也可以简单地改变配置来使用 Apache Commons DBCP 或者 c3p0 连接池。

JdbcTemplate 提供了多种 ResultSet 到 POJO 映射的功能并能将错误码转换为 Spring 便利的 DAO(数据访问对象)异常体系。自 Hive 0.10 开始,JDBC 驱动可产生有意义的错误码,可以轻松的区别 Spring 的 TransientDataAccessException 与 NonTransientDataAccessException。暂时性的(transient)异常表示可以进行重试操作而且可能会成功,而非暂时性的(nontransient)异常表示重试操作不会成功。

使用 JdbcTemplate 的 PasswordRepository 实现如示例 12-11 所示。

示例 12-11 以 JdbcTemplate 实现 PasswordRepository

P202a

由于需要替换脚本中的变量,processPasswordFile 的实现显得有些冗长。请参考示例代码获取更详细的信息。注意 Spring 提供的工具类 SimpleJdbcTestUtils 是测试包中的一部分,它通常用来对关系型数据库执行 DDL 脚本,但是当需要执行没有变量替换的 HiveQL 脚本时,它就可以派上用场了。

12.1.5 使用 Hive 分析 Apache 日志文件

接下来,使用 Hive 对 Apache HTTPD 的日志文件进行简单分析。运行这个分析的配置与之前使用 HiveTemplate 分析 password 文件的配置类似。示例 12-12 中的 HiveQL 脚本会产生一个包含每个 URL 累计点击数的文件。它也会提取最少与最多点击数,并提供一个表格,以简单图表的形式展现点击数的分布情况。

示例 12-12 基本 Apache HTTPD 日志分析的 HiveQL

P202b

P203a

这个示例使用了工具类库 hive-contrib.jar,其中包含可读取和解析 Apache 日志文件格式的序列化器(serializer)/反序列化器(deserializer)。hive-contrib.jar 可由 Maven 中心库下载或直接通过源码构建。我们已经将 hive-contrib.jar 的位置参数化,但另外一个可选的方案就是也可以将这个 jar 复制到所有执行任务的机器中,并将其放到 Hadoop 库目录下。执行结果将会存储在本机目录内。这个程序的代码位于./hadoop/hive。请参考示例目录内的 readme 文件来获取更详细的程序运行信息。在 hive_uri_hits 目录中可以看到示例的数据内容,如示例 12-13 所示。

示例 11-13 每个 URI 的点击统计

P203b

hive_histogram 目录的内容显示有 1 个 URI 已经被请求了 22 次,有 3 个 URL 各被单击了 4 次,有 74 个 URL 只被单击了 1 次,这告诉我们哪些 URL 缓存起来可以带来更大的好处。示例应用程序介绍了两种执行 Hive 命令的方法,分别使用了 HiveTemplate 和 HiveRunner。HiveRunner 的配置如示例 12-14 所示。

示例 12-14 使用 HiveRunner 运行 Apache 日志文件分析

P203c

P204

这个结果集非常小,可以使用 UNIX 命令行工具来分析,不过 Hadoop 能够把要分析的数据扩展到非常大的集合。Hadoop 也能够让我们以很低的成本存储原始数据,因此可以重新进行分析而不会丢失任何信息,这种信息丢失通常是因为保持历史数据的摘要所导致的。

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。