A leitura e análise de dados da tabela HBase é um requisito para aprender HBaseAPI

índice

1. Conceitos importantes de HBaseAPI

1. Varredura

 2. Resultado 

3. Varredura do Filtro

2. Análise de caso --- aprendizagem HBaseAPI

1. Exigir

2. Pensando

 3. Código


1. Conceitos importantes de HBaseAPI

1. Varredura

A tabela de dados no HBase realiza a fragmentação dos dados dividindo-os em regiões. Cada região é associada a um intervalo de RowKey e os dados em cada região são organizados na ordem lexicográfica de RowKey.

É com base neste design que o HBase pode facilmente lidar com este tipo de consulta: "Especifique um intervalo de RowKey e obtenha todos os registros nesse intervalo". Este tipo de consulta é chamado de Scan no HBase. Claro, se você não o especificar , ele estará cheio. Varredura da tabela, a seguir está uma consulta é um acesso RPC, retornar o conjunto de resultados para o cliente.

1. Construir varredura, especificar startRow e stopRow, se não for especificado, uma varredura completa da tabela será realizada

2. Obtenha ResultScanner

3. Percorra os resultados da consulta

4. Feche o ResultScanner

 2. Resultado 

Encapsular a varredura como um objeto de resultado e devolvê-la ao cliente.

3. Varredura do Filtro

O filtro pode definir mais valores de condição para os registros retornados com base no conjunto de resultados de Scan. Essas condições podem ser relacionadas a RowKey, nome da coluna ou valor da coluna, e várias condições de filtro podem ser combinadas em Juntos, geralmente combinados ser FilterList, mas geralmente não recomendado, pode haver o risco de vazamento de dados.

  • Cada vez que o cliente envia uma solicitação de varredura para o RegionServer, ele receberá de volta um lote de dados (o número de resultados recuperados a cada vez é determinado pelo cache), e então o colocará no cache de resultados desta vez
  • Cada vez que o aplicativo lê dados, eles são obtidos do cache de resultados local. Se os dados no cache de resultados foram lidos, o cliente enviará uma solicitação de varredura ao RegionServer novamente para obter mais dados

2. Análise de caso --- aprendizagem HBaseAPI

1. Exigir

Analise os dados na tabela a seguir. Os dados relatados regularmente são relatados em minutos. O valor após minutos = 2 # 1 # 0 são os dados a serem analisados ​​e resumidos. Agora, quero resumir os dados de 20200706 deste dia, desde que é incremental Ao ler a análise de dados, o carimbo de hora será mantido na tabela LastJobTime.Se o modifyTime na tabela for maior que o carimbo de hora registrado após cada análise, novos dados serão lidos.

2. Pensando

  • Percorra o conjunto de resultados do Resultado e retire diretamente os valores de campo determinados do Resultado de acordo com CF e coluna, como c, ci, ct e outros campos acima
  • Os campos incertos são os campos d: 1300, d: 1305, etc., que são escritos dinamicamente na tabela de acordo com o tempo. Primeiro, atravesse a célula, retire o Qualify de acordo com a célula, leia e analise todos os campos de acordo com com comprimento de 4 ou mais, até agora podemos obter os dados de valor escritos dinamicamente na coluna de tempo 

   Se você tiver a sorte de ler aqui, apenas entenda meu pensamento e não precisará entrar nos cenários de negócios acima.

 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(_))
  }
}

 

O exemplo acima é um exemplo de leitura e análise dos dados da tabela da empresa. Claro, a leitura também pode ser otimizada de acordo com a chave de linha, porque a chave de linha é um design personalizado e o nome do host + canal md5 é criptografado e com hash, e pode ser especificado de acordo com o intervalo de varredura da chave de linha ---- withStartRow () e withStopRow (), juntamente com a velocidade de análise de dados incremental, são perfeitos.

 Referência: https://www.sohu.com/a/284932698_100109711

 

Acho que você gosta

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