Spark 2.X 版本读写 Hbase 最佳实践

477 阅读3分钟

Spark 读写 Hbase 响应的官方参考资料较少,最近正好在测试 Hbase,集成 Spark 时了解的下这方面知识,做一个简单总结,当前 Spark On Hbase 的驱动主要有两种实现,官方驱动和 hortonworks 的 shc。

hbase-connectors

纯官方驱动,以前是单独的项目,现在和 Kafka 驱动集成在一起了。优点是使用便捷,直接在 maven 中添加引用。一般情况无使用冲突。

但也有比较明显的缺陷:

  • 使用起来较为复杂,需要自己构建 Hbase 数据结构,能找到的示例很少,不过驱动中内含了一些示例,可以很好的帮我们快速跑通,例如,这里,链接失效的话可以自己进入项目找一找 Example 结尾的文件。
  • 只能构建一个 JavaHBaseContext,调用其提供的方法,但是只找到了 RDD 的相关方法,所以对 Spark 2.X 常用的 DataFrame 可能不太友好。

hortonworks-spark

hortonworks 贡献的驱动,与官方驱动相比,又加了一些封装,使得使用方面与其他内置驱动(jdbc 等)基本相同,对 DataFrame 的支持较为友好。

但最大的问题是引用问题:

  • 官方 jar 包没发布的到 spark-packages.org,参考,要通过 spark packages 的形式使用还需要指定 hortonworks 的 repository,受限于网络环境,不走代理基本是是用不了的。

Note: com.hortonworks:shc-core:1.1.1-2.1-s_2.11 has not been uploaded to spark-packages.org, but will be there soon.

  • 如果通过 maven 的方式引用 jar 包,参考,还是需要指定 maven 的 repository 到 hortonworks。

Note: this artifact is located at Hortonworks repository (repo.hortonworks.com/content/rep…)

  • 所以只能通过指定 hortonworks 仓库自动下载依赖 jar 包,和自己事先准备 jar 包并在 spark-submit 时添加 --jars 这些 jar 包的的方式来使用 shc,参考

受限于网络原因 hortonworks 仓库连接实在过慢,自己打包的话按照 issue 中讨论的情况是可以自己添加引用的 jar 包跑起来的,但是受限于版本,链接里的命令基本都过时了,通过不断的调整 jar 包版本,我也按照引用 jar 包的方式跑通了一次,但是未来 spark、hbase、shc 的版本发生变化,仍然会有问题,所以应该找寻一种解决问题的方法论,而不是直接给出怎么 run 的命令。

  • 首先分析自己的 Spark 版本和 Hbase 版本,截止当前 shc 支持的 Spark 和 Hbase 版本分别为 2.4.0 和 2.0.4,参考,如果正在使用的版本与此相差不大或者低于此版本,那么使用 shc 应该是没有问题的。
  • 在 shc 仓库中找寻最匹配自己的 Spark 和 Hbase 版本的 branch 或者 tag,如果能找打 release 包就直接下载否则使用源码进行编译。拿到 shc-core 的 jar 包。可以直接上传到 classpath,也可以使用 maven system scope 打包进自己的项目。
  • 分析 shc 的源码发现它主要使用了 hbase 的 server、client 的一些类名,所以我们只需要把这些依赖添加到自己的项目的 maven 中就行了,可以参考它自己的 pom,经过测试只需要添加 hbase-server 和 hbase-mapreduce 就可以跑起来,其它 phoenix、avro 可能是使用了相关功能才需要。
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-server</artifactId>
            <version>2.0.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-mapreduce</artifactId>
            <version>2.0.4</version>
        </dependency>
  • 运行时有可能一些工具包还是有冲突,这是时候安装 maven 树添加 exclusions 就可以了,主要可能冲突的是 netty 和 jackson 包,这里我在 hbase 的 dependency 里都将其 exclusion 了。

关于使用,shc 的封装还是很不错的,基本屏蔽了 Hbase 的许多细节,只需要额外制定一个 Hbase table 的 Catalog 就可以了,由于 官方示例 已经放出了 Scala 版本的详细示例,我在这里就记录一下 Java 示例。

        String catalog = "{\r\n"
                + "\"table\":{\"namespace\":\"default\", \"name\":\"demo_person_with_row_key\", \"tableCoder\":\"PrimitiveType\"},\r\n"
                + "\"rowkey\":\"idname\",\r\n" + "\"columns\":{\r\n"
                + "\"idname\":{\"cf\":\"rowkey\", \"col\":\"idname\", \"type\":\"string\"},\r\n"
                + "\"id\":{\"cf\":\"general\", \"col\":\"id\", \"type\":\"string\"},\r\n"
                + "\"name\":{\"cf\":\"general\", \"col\":\"name\", \"type\":\"string\"},\r\n"
                + "\"mobile\":{\"cf\":\"general\", \"col\":\"mobile\", \"type\":\"string\"}\r\n" + "}\r\n" + "}";
        Map<String, String> map = new HashMap();
        map.put(HBaseTableCatalog.tableCatalog(), catalog);
        map.put(HBaseTableCatalog.newTable(), "5");
	Dataset<Row> df = spark.read().options(map).format("org.apache.spark.sql.execution.datasources.hbase").load();
    	df.show();
//        df.write().options(map).format("org.apache.spark.sql.execution.datasources.hbase").save();