Flink数据实时写入HBase

  • main

    object MyHbaseSinkTest {
    def main(args: Array[String]): Unit = {
    //环境
    val env = StreamExecutionEnvironment.getExecutionEnvironment

    复制代码
      /**
       * 获取基础参数
       */
      val bootstrapserversnew = Contant.BOOTSTRAP_SERVERS_NEW
      import org.apache.flink.api.scala._
    
      /**
       * 定义kafka-source得到DataStream
       */
      val topics = "vs_merging_middle_topic"
      //将kafka中数据反序列化,
      val valueDeserializer: DeserializationSchema[String] = new SimpleStringSchema()
    
      val properties = new Properties()
      properties.put("bootstrap.servers", bootstrapserversnew)
      properties.put("group.id", "flink_hbase_sink_consumer2")
      properties.put("auto.offset.reset", Contant.AUTO_OFFSET_RESET_VALUE)
    
      println(Contant.BOOTSTRAP_SERVERS_NEW)
      val kafkaSinkDStream = env.addSource(new FlinkKafkaConsumer[String](topics, valueDeserializer, properties))
    
      kafkaSinkDStream.flatMap(data => {
        val jsonData = JSON.parseObject(data)
        val table = jsonData.getString("table")
        val rowkey = jsonData.getJSONObject("data").get("id").toString
        val jsonResult = jsonData.getJSONObject("data")
        import scala.collection.JavaConversions._
        jsonResult.keySet().map(key => {
          HbaseValueBean("variable_system:" + table, rowkey, "info", key, jsonResult.get(key).toString)
        })
      })
        .addSink(MyHbaseSinkSingle)
    
      env.execute(this.getClass.getSimpleName)
    }

    }

  • bean

    case class HbaseValueBean(
    tableName : String ,
    rowkey : String ,
    family : String ,
    column : String ,
    value : String
    )

  • HBase-Sink

    object MyHbaseSinkSingle extends RichSinkFunction[HbaseValueBean] {
    private var putsResult: List[Put] = collection.immutable.ListPut
    private var hbaseConn: Connection = null
    private var maxSize = 100

    复制代码
    /**
     * 开始,打开连接
     *
     * @param parameters
     */
    override def open(parameters: Configuration): Unit = {
      hbaseConn = HBaseUtils.getHbaseConnNotPoolNew
      maxSize = parameters.getInteger("maxSize" , 100)
      //    val lastInvokeTime = System.currentTimeMillis
    }
    
    /**
     * 数据处理
     *
     * @param value
     * @param context
     */
    override def invoke(value: HbaseValueBean, context: SinkFunction.Context[_]): Unit = {
      if (value.tableName == "variable_system:risk_task") {
    
        import scala.collection.JavaConversions._
        /**
         * rowkey与put
         */
        val put = new Put(value.rowkey.getBytes())
        PutUtils.setDataString(put , value.family , value.column , value.value)
        putsResult = putsResult :+ put
        println(s"puts-size:${putsResult.size}")
    
        /**
         * 判断输出
         */
        if (putsResult.size() >= maxSize) {
          val table = hbaseConn.getTable(TableName.valueOf(value.tableName))
          table.put(putsResult)
    
          println("进行sink")
          println(s"table:${value.tableName} , 已经达到:${maxSize} , 已存储;")
          println(s"puts:${putsResult}")
    
          /**
           * 因为Java与Scala集合转换,所以这里是没有scala的清除方法的
           */
          putsResult = collection.immutable.List[Put]()
          table.close()
        }
      }
    }
    
    /**
     * 满足条件输出数据并且关闭连接
     */
    override def close(): Unit = {
      hbaseConn.close()
    }

    }

  • HBase-Connect

    def getHbaseConnNotPoolNew: Connection = {
    var conf: Configuration = HBaseConfiguration.create
    conf.set("hbase.zookeeper.quorum", "host:port")
    conf.set("hbase.zookeeper.property.clientPort", "port")
    conf.set("hbase.master", "16000")
    conf.set("hbase.rootdir", "dir")
    val conn = ConnectionFactory.createConnection(conf)
    conn
    }

  • HBase-Utiles

    object PutUtils {
    def setDataString(put: Put,cf:String,col:String,data:String): Unit ={
    put.addColumn(Bytes.toBytes(cf) , Bytes.toBytes(col) , Bytes.toBytes(data))
    }

    复制代码
    def setDataStringGetPut(put: Put,cf:String,col:String,data:String): Put ={
      put.addColumn(Bytes.toBytes(cf) , Bytes.toBytes(col) , Bytes.toBytes(if(data!= null && data != "") data else "null"))
    }

    }

部署

复制代码
#!/bin/bash
flink run -m yarn-cluster \
-c com.xxxx.flink.MyHbaseSinkTest \
-p 8 \
/home/cdh/xxxx/2020/11/FlinkToKuduDemo/realtime_source_dw.jar

注意事项

  1. 不能够以Spark Streaming的方式来理解Fink的Source和Sink,如果使用客户端是无法针对每个分区进行连接数据处理的,使用Sink可以建立全局连接进行数据存储;
  2. 由上面,全局连接,全局数据处理导致的问题就是不能够每个分区建立线程不安全的集合进行数据存储,必须使用线程安全的集合,也就是不可变的集合进行数据处理,那么使用了Scala之间的集合转换就要注意方法的使用,很多Java结合的方法Scala是没有的,所以一般的清空操作还是使用地址替换重新复制覆盖的方式来进行
  3. addSink的之前的DataStream的数据类型一定是与自定义Sink的操作类型一致的,是针对最后的数据类型进行处理存储的;
相关推荐
TDengine (老段)10 分钟前
TDengine 转换函数 TO_JSON 用户手册
android·大数据·数据库·json·时序数据库·tdengine·涛思数据
rgb2gray1 小时前
增强城市数据分析:多密度区域的自适应分区框架
大数据·python·机器学习·语言模型·数据挖掘·数据分析·llm
expect7g1 小时前
Paimon源码解读 -- PartialUpdateMerge
大数据·后端·flink
yumgpkpm3 小时前
腾讯云TBDS与CDH迁移常见问题有哪些?建议由CDH迁移到CMP 7.13 平台(类Cloudera CDP,如华为鲲鹏 ARM 版)
hive·hadoop·zookeeper·flink·spark·kafka·hbase
艾莉丝努力练剑5 小时前
【优选算法必刷100题】第031~32题(前缀和算法):连续数组、矩阵区域和
大数据·人工智能·线性代数·算法·矩阵·二维前缀和
能鈺CMS5 小时前
能鈺CMS · 虚拟发货源码
java·大数据·数据库
非著名架构师6 小时前
极端天气下的供应链韧性:制造企业如何构建气象风险防御体系
大数据·人工智能·算法·制造·疾风气象大模型·风光功率预测
做萤石二次开发的哈哈8 小时前
11月27日直播预告 | 萤石智慧台球厅创新场景化方案分享
大数据·人工智能
Hello.Reader8 小时前
使用 Flink CDC 搭建跨库 Streaming ETLMySQL + Postgres → Elasticsearch 实战
大数据·elasticsearch·flink
用户199701080188 小时前
1688图片搜索API | 上传图片秒找同款 | 相似商品精准推荐
大数据·数据挖掘·图片资源