Spark序列化错误

时间:2014-05-12 22:11:07

标签: hbase apache-spark

我正在努力学习spark + scala。我想从HBase读取,但没有mapreduce。 我创建了一个简单的HBase表 - “test”,并在其中进行了3次放入。我想通过spark读取它(没有使用mapreduce的HBaseTest)。我试图在shell上运行以下命令

val numbers = Array(
  new Get(Bytes.toBytes("row1")), 
  new Get(Bytes.toBytes("row2")), 
  new Get(Bytes.toBytes("row3")))
val conf = new HBaseConfiguration()
val table = new HTable(conf, "test")
sc.parallelize(numbers, numbers.length).map(table.get).count()

我一直收到错误 - org.apache.spark.SparkException:作业已中止:任务不可序列化:java.io.NotSerializableException:org.apache.hadoop.hbase.HBaseConfiguration

有人可以帮助我,我怎样才能创建一个使用serialzable配置的Htable

感谢

2 个答案:

答案 0 :(得分:4)

您的问题是table不可序列化(而不是它的成员conf),并且您试图通过在map内使用它来序列化它。他们尝试阅读HBase的方式不太正确,看起来你尝试了一些特定的Get,然后尝试并行执行。即使你确实这样做了,这实际上也不会随着你进行随机读取而扩展。你想要做的是使用Spark执行表扫描,这是一个应该帮助你做的代码片段:

val conf = HBaseConfiguration.create()
conf.set(TableInputFormat.INPUT_TABLE, tableName)

sc.newAPIHadoopRDD(conf, classOf[TableInputFormat],
  classOf[org.apache.hadoop.hbase.io.ImmutableBytesWritable],
  classOf[org.apache.hadoop.hbase.client.Result])

这将为您提供包含构成行的NaviagableMap的RDD。下面是如何将NaviagbleMap更改为字符串的正常Scala映射:

...
.map(kv => (kv._1.get(), navMapToMap(kv._2.getMap)))
.map(kv => (Bytes.toString(kv._1), rowToStrMap(kv._2)))

def navMapToMap(navMap: HBaseRow): CFTimeseriesRow =
  navMap.asScala.toMap.map(cf =>
    (cf._1, cf._2.asScala.toMap.map(col =>
      (col._1, col._2.asScala.toMap.map(elem => (elem._1.toLong, elem._2))))))

def rowToStrMap(navMap: CFTimeseriesRow): CFTimeseriesRowStr =
  navMap.map(cf =>
    (Bytes.toString(cf._1), cf._2.map(col =>
      (Bytes.toString(col._1), col._2.map(elem => (elem._1, Bytes.toString(elem._2)))))))

最后一点,如果您确实想要尝试并行执行随机读取,我相信您可以将HBase表初始化放在map内。

答案 1 :(得分:2)

当你做

时会发生什么

@transient val conf = new HBaseConfiguration

UPDATE 显然,HBase提交的任务的其他部分也不可序列化。其中每一项都需要解决。

  • 考虑实体在线路的两侧是否具有相同的含义/语义。肯定没有任何联系。 HBaseConfiguration应该被序列化。但是在原语之上构建的原语和简单对象 - 并且不包含上下文敏感数据 - 可以包含在序列化中

  • 对于上下文相关的实体 - 包括HBaseConfiguration和任何面向连接的数据结构 - 您应该将它们标记为@transient,然后在readObject()方法中,它们应该使用与客户端环境相关的值进行实例化。