HBase operation: Spark read HBase snapshot demo share

Keywords: Big Data HBase Apache Hadoop Spark

**Before * * I shared with you a small demo of Spark reading HBase directly through the interface: HBase-Spark-Read-Demo However, if the amount of data is very large, Spark's direct scanning of HBase table will inevitably cause a lot of pressure on HBase cluster. Based on this, today I'd like to share with you the way spark directly reads HBase HFile files through Snapshot.

First, we create an HBase table: test, and insert several pieces of data, as follows:

hbase(main):003:0> scan 'test'
ROW                                              COLUMN+CELL                                                                                                                                                                                                                       
 r1                                              column=f:name, timestamp=1583318512414, value=zpb                                                                                               
 r2                                              column=f:name, timestamp=1583318517079, value=lisi                                                                                               
 r3                                              column=f:name, timestamp=1583318520839, value=wang                                                                                               

Next, we create a snapshot of the HBase table. Its path on HDFS is as follows:

hbase(main):005:0> snapshot 'test', 'test-snapshot'
0 row(s) in 0.3690 seconds

$ hdfs dfs -ls /apps/hbase/data/.hbase-snapshot
Found 1 items
drwxr-xr-x   - hbase hdfs          0 2020-03-21 21:24 /apps/hbase/data/.hbase-snapshot/test-snapshot

The code is as follows:

import org.apache.hadoop.fs.Path
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.hbase._
import org.apache.hadoop.mapreduce.Job
import org.apache.hadoop.hbase.client.Scan
import org.apache.hadoop.hbase.mapreduce.{TableInputFormat, TableSnapshotInputFormat}
import org.apache.hadoop.hbase.protobuf.ProtobufUtil
import org.apache.hadoop.hbase.util.{Base64, Bytes}
import org.apache.spark.{SparkConf, SparkContext}


object SparkReadHBaseSnapshotDemo {

  //   Main function
  def main(args: Array[String]) {

    // Set spark access portal
    val conf = new SparkConf().setAppName("SparkReadHBaseSnapshotDemo")
      .set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
      .setMaster("local")//debugging

    val sc = new SparkContext(conf)
    // Get HbaseRDD
    val job = Job.getInstance(getHbaseConf())
    TableSnapshotInputFormat.setInput(job, "test-snapshot", new Path("/user/tmp"))

    val hbaseRDD = sc.newAPIHadoopRDD(job.getConfiguration, classOf[TableSnapshotInputFormat],
      classOf[org.apache.hadoop.hbase.io.ImmutableBytesWritable],
      classOf[org.apache.hadoop.hbase.client.Result])
      hbaseRDD.map(_._2).map(getRes(_)).count()
  }


  def getRes(result: org.apache.hadoop.hbase.client.Result): String = {
    val rowkey = Bytes.toString(result.getRow())
    val name = Bytes.toString(result.getValue("f".getBytes, "name".getBytes))
    println(rowkey+"---"+name)
    name
  }
  // Construct Hbase configuration information
  def getHbaseConf(): Configuration = {
    val conf: Configuration = HBaseConfiguration.create()
    conf.set(TableInputFormat.SCAN, getScanStr())
    conf
  }

  // Get scanner
  def getScanStr(): String = {
    val scan = new Scan()
    // scan.set
    val proto = ProtobufUtil.toScan(scan)
    Base64.encodeBytes(proto.toByteArray())
  }
}

**Note: * * the above code needs to put the core-site.xml & hdfs-site.xml & hbase-site.xml file in the resource directory resources. Otherwise, it should be configured in the code as follows:

package com.xcar.etl

import org.apache.hadoop.fs.Path
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.hbase._
import org.apache.hadoop.mapreduce.Job
import org.apache.hadoop.hbase.client.Scan
import org.apache.hadoop.hbase.mapreduce.{TableInputFormat, TableSnapshotInputFormat}
import org.apache.hadoop.hbase.protobuf.ProtobufUtil
import org.apache.hadoop.hbase.util.{Base64, Bytes}
import org.apache.spark.{SparkConf, SparkContext}


object SparkReadHBaseSnapshotDemo2 {

  val HBASE_ZOOKEEPER_QUORUM = "xxxx.com.cn"

  //   Main function
  def main(args: Array[String]) {

    // Set spark access portal
    val conf = new SparkConf().setAppName("SparkReadHBaseSnapshotDemo2")
      .set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
      .setMaster("local")//debugging

    val sc = new SparkContext(conf)
    // Get HbaseRDD
    val job = Job.getInstance(getHbaseConf())
    TableSnapshotInputFormat.setInput(job, "test-snapshot", new Path("/user/tmp"))

    val hbaseRDD = sc.newAPIHadoopRDD(job.getConfiguration, classOf[TableSnapshotInputFormat],
      classOf[org.apache.hadoop.hbase.io.ImmutableBytesWritable],
      classOf[org.apache.hadoop.hbase.client.Result])
    hbaseRDD.map(_._2).map(getRes(_)).count()
  }

  def getRes(result: org.apache.hadoop.hbase.client.Result): String = {
    val rowkey = Bytes.toString(result.getRow())
    val name = Bytes.toString(result.getValue("f".getBytes, "name".getBytes))
    println(rowkey+"---"+name)
    name
  }

  // Construct Hbase configuration information
  def getHbaseConf(): Configuration = {
    val conf: Configuration = HBaseConfiguration.create()
    conf.set("hbase.zookeeper.property.clientPort", "2181")
    conf.set("zookeeper.znode.parent", "/hbase")
    conf.set("hbase.zookeeper.quorum", HBASE_ZOOKEEPER_QUORUM)
    conf.set("hbase.rootdir", "/apps/hbase")
    // Set the table name of the query
    conf.set(TableInputFormat.INPUT_TABLE, "test")
    conf.set("fs.defaultFS","hdfs://xxxxxx:8020") 
    conf.set(TableInputFormat.SCAN, getScanStr())
    conf
  }

  // Get scanner
  def getScanStr(): String = {
    val scan = new Scan()
    // scan.set
    val proto = ProtobufUtil.toScan(scan)
    Base64.encodeBytes(proto.toByteArray())
  }
}

TableSnapshotInputFormat.setInput method parameter resolution:

public static void setInput(org.apache.hadoop.mapreduce.Job job,
                            String snapshotName,
                            org.apache.hadoop.fs.Path restoreDir)
                            throws IOException
//Parameter resolution:
job - the job to configure
snapshotName - the name of the snapshot to read from
restoreDir - a temporary directory to restore the snapshot into. 
Current user should have write permissions to this directory, and this should not be a subdirectory of rootdir. 
After the job is finished, restoreDir can be deleted.

pom.xml file used in the project:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zpb.test</groupId>
    <artifactId>spark-read-hbase-snapshot-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spark-read-hbase-snapshot-demo</name>
    <url>http://maven.apache.org</url>

    <repositories>
        <repository>
            <id>cloudera</id>
            <url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
        </repository>
    </repositories>

    <properties>
        <cdh.hbase.version>1.2.0-cdh5.7.0</cdh.hbase.version>
        <cdh.spark.version>1.6.0-cdh5.7.0</cdh.spark.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.10</artifactId>
            <version>${cdh.spark.version}</version>
            <!--<scope>provided</scope>-->
        </dependency>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-server</artifactId>
            <version>${cdh.hbase.version}</version>
        </dependency>
    </dependencies>
</project>

Reprint please indicate the source! Welcome to my WeChat official account [HBase working notes]

Posted by vapokerpro on Fri, 17 Apr 2020 08:28:05 -0700