Снимки Spark и HBase
в предположении, что мы могли бы получить доступ к данным намного быстрее, если вытаскивать непосредственно из HDFS вместо использования API HBase, мы пытаемся построить RDD на основе моментального снимка таблицы из HBase.
Итак, у меня есть снимок под названием "dm_test_snap". Кажется, я могу заставить работать большую часть конфигурации, но мой RDD равен null (несмотря на наличие данных в самом снимке).
у меня чертовски много времени, чтобы найти пример любого, кто делает автономный анализ Снимки HBase с Spark, но я не могу поверить, что я один пытаюсь заставить это работать. Любая помощь или предложения очень ценятся.
вот фрагмент моего кода:
object TestSnap {
def main(args: Array[String]) {
val config = ConfigFactory.load()
val hbaseRootDir = config.getString("hbase.rootdir")
val sparkConf = new SparkConf()
.setAppName("testnsnap")
.setMaster(config.getString("spark.app.master"))
.setJars(SparkContext.jarOfObject(this))
.set("spark.executor.memory", "2g")
.set("spark.default.parallelism", "160")
val sc = new SparkContext(sparkConf)
println("Creating hbase configuration")
val conf = HBaseConfiguration.create()
conf.set("hbase.rootdir", hbaseRootDir)
conf.set("hbase.zookeeper.quorum", config.getString("hbase.zookeeper.quorum"))
conf.set("zookeeper.session.timeout", config.getString("zookeeper.session.timeout"))
conf.set("hbase.TableSnapshotInputFormat.snapshot.name", "dm_test_snap")
val scan = new Scan
val job = Job.getInstance(conf)
TableSnapshotInputFormat.setInput(job, "dm_test_snap",
new Path("hdfs://nameservice1/tmp"))
val hBaseRDD = sc.newAPIHadoopRDD(conf, classOf[TableSnapshotInputFormat],
classOf[org.apache.hadoop.hbase.io.ImmutableBytesWritable],
classOf[org.apache.hadoop.hbase.client.Result])
hBaseRDD.count()
System.exit(0)
}
}
обновление для включения решения Хитрость заключалась в том, что, как упоминал @Holden ниже, conf не проходил. Чтобы исправить это, я смог заставить его работать, изменив этот вызов newAPIHadoopRDD на это:
val hBaseRDD = sc.newAPIHadoopRDD(job.getConfiguration, classOf[TableSnapshotInputFormat],
classOf[org.apache.hadoop.hbase.io.ImmutableBytesWritable],
classOf[org.apache.hadoop.hbase.client.Result])
был второй вопрос это также было подчеркнуто ответом @victor, что я не проходил сканирование. Чтобы исправить это, я добавил эту строку и способ:
conf.set(TableInputFormat.SCAN, convertScanToString(scan))
def convertScanToString(scan : Scan) = {
val proto = ProtobufUtil.toScan(scan);
Base64.encodeBytes(proto.toByteArray());
}
Это также позволяет мне вытащить эту строку из conf.набор команд:
conf.set("hbase.TableSnapshotInputFormat.snapshot.name", "dm_test_snap")
*Примечание: это было для HBase версии 0.96.1.1 на CDH5.0
окончательный полный код для ссылки:
object TestSnap {
def main(args: Array[String]) {
val config = ConfigFactory.load()
val hbaseRootDir = config.getString("hbase.rootdir")
val sparkConf = new SparkConf()
.setAppName("testnsnap")
.setMaster(config.getString("spark.app.master"))
.setJars(SparkContext.jarOfObject(this))
.set("spark.executor.memory", "2g")
.set("spark.default.parallelism", "160")
val sc = new SparkContext(sparkConf)
println("Creating hbase configuration")
val conf = HBaseConfiguration.create()
conf.set("hbase.rootdir", hbaseRootDir)
conf.set("hbase.zookeeper.quorum", config.getString("hbase.zookeeper.quorum"))
conf.set("zookeeper.session.timeout", config.getString("zookeeper.session.timeout"))
val scan = new Scan
conf.set(TableInputFormat.SCAN, convertScanToString(scan))
val job = Job.getInstance(conf)
TableSnapshotInputFormat.setInput(job, "dm_test_snap",
new Path("hdfs://nameservice1/tmp"))
val hBaseRDD = sc.newAPIHadoopRDD(job.getConfiguration, classOf[TableSnapshotInputFormat],
classOf[org.apache.hadoop.hbase.io.ImmutableBytesWritable],
classOf[org.apache.hadoop.hbase.client.Result])
hBaseRDD.count()
System.exit(0)
}
def convertScanToString(scan : Scan) = {
val proto = ProtobufUtil.toScan(scan);
Base64.encodeBytes(proto.toByteArray());
}
}
3 ответов
глядя на информацию о задании, он делает копию объекта conf, который вы ему предоставляете (The Job makes a copy of the Configuration so that any necessary internal modifications do not reflect on the incoming parameter.
) поэтому, скорее всего, информация, которую вам нужно установить на объекте conf, не передается в Spark. Вместо этого вы можете использовать TableSnapshotInputFormatImpl
который имеет аналогичный метод, который работает на объектах conf. Могут потребоваться дополнительные вещи, но сначала пройти через проблему, это кажется наиболее вероятной причиной.
как указано в комментариях, другой вариант-использовать job.getConfiguration
для получения обновленной конфигурации из объекта задания.
вы неправильно настроили задание M/R: Это пример в Java о том, как настроить M/R над снимками:
Job job = new Job(conf);
Scan scan = new Scan();
TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,
scan, MyTableMapper.class, MyMapKeyOutput.class,
MyMapOutputValueWritable.class, job, true);
}
вы, определенно, пропустили сканирование. Я предлагаю вам взглянуть на реализацию initTableSnapshotMapperJob от TableMapReduceUtil, чтобы получить представление о настройке задания в Spark/Scala.
вот полная конфигурация в MapReduce Java
TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, // Name of the snapshot
scan, // Scan instance to control CF and attribute selection
DefaultMapper.class, // mapper class
NullWritable.class, // mapper output key
Text.class, // mapper output value
job,
true,
restoreDir);