作者:Syn良子 出处:http://www.cnblogs.com/cssdongl/p/7449682.html 转载请注明出处
最近在折腾pyspark的HbaseConverters,由于资料太少折腾了好一会儿才明白,特此分享给大家.
问题背景
最近在使用pyspark写hbase的过程中发现,会报以下类似的错误
这是由于最终计算结果存入hbase的时候pyspark无法找到相关的converter造成的.啥?你问为啥要找converter,这是因为Java和Scala都可以支持组装Hbase的Put然后存入Hbase,但是Python这块儿spark API是后妈生的,暂时还不能直接支持,所以需要转换.
问题详解
这个HBaseConverters模块位于spark-examples*.jar包下,据我挨个检查,spark1.4和spark1.6都有这个模块,而spark.2.x已经没有了,但是spark2.x上我测试了可以使用1.6的spark-examples_2.10-1.6.3.jar中的HBaseConverters来读写Hbase,完全没有问题.而Spark1.4和Spark1.6的HBaseConverters我推荐用后者,理由如下.
Spark1.4的HBaseConverters模块
这是一个scala文件,里面有4个class,细心观察的同学会发现,上面2个是读取Hbase用,下面2个是写入用,它们都继承了
org.apache.spark.api.python.Converter类,这个是pyspark的API,最终会调用四个子类来进行相应的读写.
Spark1.6的HBaseConverters模块
恩,仔细观察2个截图中的代码,唯一的区别在于第一个HBaseResultToStringConverter这个读取Hbase的Result转换类.
对,我想强调的就是这个转换类。Spark1.4的这个转换类仔细看代码
class HBaseResultToStringConverter extends Converter[Any, String] {
override def convert(obj: Any): String = {
val result = obj.asInstanceOf[Result]
Bytes.toStringBinary(result.value())
}
}
这个读取hbase的转换类得到Result后,最终返回的只是result.value()也就是列值.
然后观察spark1.6的这个转换类
class HBaseResultToStringConverter extends Converter[Any, String] {
override def convert(obj: Any): String = {
val result = obj.asInstanceOf[Result]
val output = result.listCells.asScala.map(cell =>
Map(
"row" -> Bytes.toStringBinary(CellUtil.cloneRow(cell)),
"columnFamily" -> Bytes.toStringBinary(CellUtil.cloneFamily(cell)),
"qualifier" -> Bytes.toStringBinary(CellUtil.cloneQualifier(cell)),
"timestamp" -> cell.getTimestamp.toString,
"type" -> Type.codeToType(cell.getTypeByte).toString,
"value" -> Bytes.toStringBinary(CellUtil.cloneValue(cell))
)
)
output.map(JSONObject(_).toString()).mkString(" ")
}
}
恩,注意中间的Map部,这个转换类首先将Result的各个部分读取出来(不止是value)封装成map,然后转换成Json字符串返回.
区别很明显了,明显1.6这个转换类更详细,我们能从中得到更多的内容.
问题总结
理解了上述HbaseConverters的本质以后,我们就能愉快的利用pyspark来快速读写hbase,要点如下
- pyspark读取hbase时,定义好keyconverter和valueconverter及hbaseconf很关键,不会配置的可以参考我上篇文章
- pyspark写入hbase时,同上定义好这几个配置,而最终需要保存到hbase的rdd,需要构造为(tablename,[rowkey,column_fm,columnname,columnvalue])这种元组字符串的格式,然后才可以成功的保存到hbase.
- pyspark的HbaeConverters所在jar包需要加入spark的classpath中去(或者spark-submmit提交时跟参数--jars将具体jar包include进去),可以参考我上篇文章最后的spark classpath配置.
本来想直接贴调试过的代码的,但是总觉得MarkDown格式的代码引用格式不好用,还是直接截图吧,大家感受下就好