La lectura y el análisis de datos de la tabla HBase es un requisito para aprender HBaseAPI

Tabla de contenido

1. Conceptos importantes de HBaseAPI

1.Escanear

 2.Resultado 

3.Escaneo del filtro

2. Análisis de casos: aprendizaje de HBaseAPI

1. Demanda

2. Pensando

 3. Código


1. Conceptos importantes de HBaseAPI

1.Escanear

La tabla de datos en HBase se da cuenta de la fragmentación de datos dividiéndola en regiones. Cada región está asociada con un rango de RowKey y los datos en cada región están organizados en el orden lexicográfico de RowKey.

Se basa en este diseño que HBase puede manejar fácilmente este tipo de consulta: "Especifique un rango RowKey y obtenga todos los registros en ese rango". Este tipo de consulta se llama Escanear en HBase. Por supuesto, si no lo especifica , estará lleno Escaneo de tabla, la siguiente es una consulta es un acceso RPC, devuelve el conjunto de resultados al cliente.

1. Genere escaneo, especifique startRow y stopRow, si no se especifica, se realizará un escaneo completo de la tabla

2. Obtenga ResultScanner

3. Recorre los resultados de la consulta

4. Cierre ResultScanner

 2.Resultado 

Encapsular el escaneo como un objeto de resultado y devolverlo al cliente.

3.Escaneo del filtro

El filtro puede establecer más valores de condición para los registros devueltos en función del conjunto de resultados de la exploración. Estas condiciones pueden estar relacionadas con la clave de fila, el nombre de la columna o el valor de la columna, y se pueden combinar varias condiciones de filtro en Juntos, generalmente combinados juntos Sea FilterList, pero generalmente no se recomienda, puede haber riesgo de fuga de datos.

  • Cada vez que el cliente envía una solicitud de escaneo al RegionServer, recuperará un lote de datos (el número de resultados recuperados cada vez lo determina el almacenamiento en caché) y luego lo pondrá en el caché de resultados esta vez
  • Cada vez que la aplicación lee datos, se obtienen de la caché de resultados local. Si se han leído los datos en el caché de resultados, el cliente enviará una solicitud de escaneo al RegionServer nuevamente para obtener más datos

2. Análisis de casos: aprendizaje de HBaseAPI

1. Demanda

Analice los datos en la siguiente tabla. Los datos reportados regularmente se reportan en minutos. El valor después de minutos = 2 # 1 # 0 son los datos que se analizarán y resumirán. Ahora quiero resumir los datos de 20200706 este día, siempre que es incremental Al leer el análisis de datos, la marca de tiempo se mantendrá en la tabla LastJobTime Si el tiempo de modificación en la tabla es mayor que la marca de tiempo registrada después de cada análisis, se leerán nuevos datos.

2. Pensando

  • Recorra el conjunto de resultados de Resultado y extraiga directamente los valores de campo determinados del Resultado de acuerdo con CF y columna, como c, ci, ct y otros campos anteriores
  • Los campos inciertos son los campos d: 1300, d: 1305, etc., que se escriben dinámicamente en la tabla de acuerdo con el tiempo. Primero, recorra la celda, saque el Calificar según la celda, lea y analice todos los campos según hasta la longitud de 4 o más, hasta ahora podemos obtener los datos de valor escritos dinámicamente en la columna de tiempo 

   Si tiene la suerte de leer aquí, simplemente comprenda mi pensamiento y no necesita entrar en los escenarios comerciales anteriores.

 3. Código

​
​
package com.kangll.hbaseapi

import java.util
import com.winner.utils.KerberosUtil
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.hbase.{Cell, CellUtil, CompareOperator, HBaseConfiguration, TableName}
import org.apache.hadoop.hbase.client.{Connection, ConnectionFactory, Get, Result, Scan, Table}
import org.apache.hadoop.hbase.filter.{SingleColumnValueFilter, SubstringComparator}
import org.apache.hadoop.hbase.util.Bytes
import org.apache.spark.SparkContext
import org.apache.spark.sql.SparkSession

import scala.collection.mutable.ListBuffer

/** ******************************************
 *
 * @AUTHOR kangll
 * @DATE 2020/8/11 14:47
 * @DESC:
 * *******************************************
 */
// 将表中解析出的数据封装为样例类
case class InOutDataHBaseTest(rowkey: String, channel: String, counterid: String, countertype: String, devicesn: String,
                              datatype: String, hostname: String, modifytime: String, datatime: String, inNum: Int, outNum: Int)

object HBaseAPI_Test_One {

  // Kerberos认证
  KerberosUtil.kerberosAuth()

  private val spark: SparkSession = SparkSession
    .builder()
    .master("local[2]")
    .appName("spark-hbase-read")
    .getOrCreate()

  private val sc: SparkContext = spark.sparkContext

  private val hbaseConf: Configuration = HBaseConfiguration.create()
  hbaseConf.set("hbase.zookeeper.quorum", "hdp301")
  hbaseConf.set("hbase.zookeeper.property.clientPort", "2181")

  def getOriginalData() = {
    import spark.implicits._
    import collection.mutable._

    // HBase 源数据库表
    val HBASE_TAG_TABLE = "trafficData"
    // 维护的时间戳,增量读取解析数据
    val HBASE_LAST_JOBTIME = "LastJobTime"
    // 创建连接对象
    val conn: Connection = ConnectionFactory.createConnection()
    val tag_table: Table = conn.getTable(TableName.valueOf(HBASE_TAG_TABLE))
    val time_table: Table = conn.getTable(TableName.valueOf(HBASE_LAST_JOBTIME))

    // 通过 rowkey 查询 HBase 表的 lastjobtime
    val get = new Get("TrafficDateTime".getBytes())
    val mdResult: Result = time_table.get(get)
    // get 直接拿到 时间戳
    val modifyTime: String = Bytes.toString(mdResult.getValue(Bytes.toBytes("t"), Bytes.toBytes("m")))

    // 查询原始数据
    val scan = new Scan()
    // 单列值过滤器 当 表中的 modifyTime 大于时间戳时 增量读取解析
    val mdValueFilter = new SingleColumnValueFilter(
      "d".getBytes(),
      "t".getBytes(),
      CompareOperator.GREATER_OR_EQUAL,
      new SubstringComparator(modifyTime) // 大于等于增量的时间戳
    )

    // scan 的条数,默认为100 扫描100 返给 客户端 Result 缓存读取
    scan.setCaching(200)
    // 设置过滤,下推到服务器 ,减少返回给客户端的数据量和 rowkey 指定范围结合更佳
    scan.setFilter(mdValueFilter)
    import collection.JavaConversions._
    val iter: util.Iterator[Result] = tag_table.getScanner(scan).iterator()
    // 存放定义的样例类
    val basicListTmp = new ListBuffer[InOutDataHBaseTest]()

    while (iter.hasNext) {
      var rowkey = ""
      var datatime = ""
      var inNum = 0
      var outNum = 0
      val result: Result = iter.next()
      val channel = Bytes.toString(result.getValue(Bytes.toBytes("d"), Bytes.toBytes("c")))
      val counterid = Bytes.toString(result.getValue(Bytes.toBytes("d"), Bytes.toBytes("ci")))
      val countertype = Bytes.toString(result.getValue(Bytes.toBytes("d"), Bytes.toBytes("ct")))
      val devicesn = Bytes.toString(result.getValue(Bytes.toBytes("d"), Bytes.toBytes("ds")))
      val datatype = Bytes.toString(result.getValue(Bytes.toBytes("d"), Bytes.toBytes("dt")))
      val hostname = Bytes.toString(result.getValue(Bytes.toBytes("d"), Bytes.toBytes("h")))
      val modifytime = Bytes.toString(result.getValue(Bytes.toBytes("t"), Bytes.toBytes("md")))

      rowkey = Bytes.toString(result.getRow)
      // 拿到 Result 的cell ,遍历 cell 拿到 columnName后判断列名取出 3#2#1 value 值 
      val cells = result.listCells()
      for (cell <- cells) {
        //  Cell工具类 获取到 列名
        var  cname = Bytes.toString(CellUtil.cloneQualifier(cell))
        if (cname.length >= 4) {
          datatime = rowkey.split("#")(1)+cname
          val cvalue = Bytes.toString(CellUtil.cloneValue(cell))
          val arr = cvalue.split("#")
          inNum = arr(0).toInt
          outNum = arr(1).toInt
          println(datatime + "--------" + inNum + "------" + outNum)
          // 将解析出的 cell 数据 放到 List 的样例类中
          basicListTmp += InOutDataHBaseTest(rowkey, channel, counterid, countertype,
            devicesn, datatype, hostname, modifytime, datatime, inNum, outNum)
        }
      }
    }
    // 获取 返回的 basicListTmp 并且返回
    val basicList: ListBuffer[InOutDataHBaseTest] = basicListTmp.map(x => InOutDataHBaseTest(x.rowkey, x.channel, x.counterid, x.countertype,
      x.devicesn, x.datatype, x.hostname, x.modifytime, x.datatime ,x.inNum, x.outNum))
    basicList.toSet
  }

  def main(args: Array[String]): Unit = {
    getOriginalData().foreach(println(_))
  }
}

 

Lo anterior es un ejemplo de lectura y análisis de los datos de la tabla de la empresa. Por supuesto, la lectura también se puede optimizar de acuerdo con la clave de fila, porque la clave de fila es un diseño personalizado, y el nombre de host + canal md5 está encriptado y hash, y puede ser especificado de acuerdo con el rango de escaneo de la clave de fila ---- withStartRow () y withStopRow (), junto con la velocidad de análisis de datos incrementales, son perfectos.

 Referencia: https://www.sohu.com/a/284932698_100109711

 

Supongo que te gusta

Origin blog.csdn.net/qq_35995514/article/details/108110553
Recomendado
Clasificación