从Kafka到Hbase的结构化流 - 需要设置自定义时间戳

时间:2018-03-26 16:53:26

标签: apache-spark pyspark apache-kafka hbase spark-structured-streaming

我正在使用

  • Spark 2.2(来自HDP 2.6.3)
  • Kafka 1.0.1
  • HBase 1.1.2(来自HDP 2.6.3)
  • shc-core-1.1.2-2.2-s_2.11-SNAPSHOT.jar使用其他scala类手动构建HBaseSinkProvider(link to a github issue

我想用这个堆栈创建一种实时ETL:

  1. 我有一个类型的数百万个对象(例如"客户")
  2. 这些对象有不同的字段(如姓名,姓氏,状态,电子邮件等)和字段版本和LastUpdateDate
  3. 当对象发生更改时,其包含所有字段和值的完整描述将发布到Kafka主题
  4. 使用Spark我有一个Structured Streaming应用程序,它使用数据流并将对象保存到HBase
  5. 以上所有内容现在都运行良好,代码就像这样(Python):

    spark \
        .readStream \
        .format('kafka') \
        .option('kafka.bootstrap.servers', 'worker01:9092,worker02:9092,worker03:9092') \
        .option('subscribe', 'youdo') \
        .option('group.id', 'spark') \
        .option('maxOffsetsPerTrigger', 100) \
        .option('startingOffsets', 'earliest') \
        .load() \
        .withColumn(
            'decoded', 
            from_json(
                col('value').cast('string'),
                schema
            )
        ) \
        .select(
            'decoded.body.*',
            'timestamp'
        ) \
        .na.fill('null') \
        .writeStream \
        .outputMode("append") \
        .format('HBase.HBaseSinkProvider') \
        .option('hbasecat', catalog) \
        .option('checkpointLocation', '/tmp/checkpoint') \
        .start() \
        .awaitTermination()
    

    现在我遇到一个问题,我不能保证,不同分区中的消息排列正确。我的意思是,例如,O可能在HBase中有一个对象的版本8,我可以使用版本7的另一个分区使用消息 - 在这种情况下,我不能更新HBase中的数据。

    首先,我尝试使用HBase加入输入流并过滤掉版本低于HBase的行:

        <...>
        .select(
            'decoded.body.*',
            'timestamp'
        ) \
        .join(
            sqlc.read \
                .format('org.apache.spark.sql.execution.datasources.hbase') \
                .options(catalog=catalog_hbase) \
                .load() \
                .select('id', col('hbase_version').cast('integer')),
            ['id'],
            'left'
        ) \
        .na.fill({'hbase_version': 0}) \
        .filter(col('version').cast('integer') > col('hbase_version'))
        <...>
    

    这样做我总是得到streamingQueryException: key not found: hbase_version - 我认为这不会因为shc而起作用,它看起来像是一个不受支持的功能。

    我看到的另一种方法是为每一行手动设置HBase行时间戳(我有LastUpdateDate属性和Version) - 我该怎么做?

    还有其他方法吗?

    生成的代码必须是Python,但编译一些jar并将它们传递给带有spark-submit的脚本是可以的。

0 个答案:

没有答案