Flink 自定义source和sink,获取kafka的key,输出指定key

本文介绍了如何在Flink中通过自定义Source和Sink来处理Kafka数据的Key。由于Flink的标准FlinkKafkaConsumer和FlinkKafkaProducer不直接提供Key的访问,作者通过使用Kafka的原始API实现了获取和设置Key的功能。同时,文章提到了使用KafkaConsumer的低级API实现Source的精确一次处理,并讨论了在Sink中实现精确一次的挑战,引用了相关博客资源作为参考。
摘要由CSDN通过智能技术生成

--------20190905更新-------  

沙雕了,可以用  JSONKeyValueDeserializationSchema,接收ObjectNode的数据,如果有key,会放在ObjectNode中

if (record.key() != null) {
            node.set("key", mapper.readValue(record.key(), JsonNode.class));
        }
        if (record.value() != null) {
            node.set("value", mapper.readValue(record.value(), JsonNode.class));
        }
        if (includeMetadata) {
            node.putObject("metadata")
                .put("offset", record.offset())
                .put("topic", record.topic())
                .put("partition", record.partition());
        }

 

-------------------

Flink 的  FlinkKafkaConsumer、FlinkKafkaProducer,在消费、生成kafka 数据的时候,不能指定key,又时候,我们又需要这个key。

val kafkaSource = new FlinkKafkaConsumer[ObjectNode]("kafka_demo", new JsonNodeDeserializationSchema(), Common.getProp)
    val sink = new FlinkKafkaProducer[String]("kafka_demo_out", new SimpleStringSchema(), Common.getProp)
    sink.setWriteTimestampToKafka(true)

    env.addSource(kafkaSource)
      .map(node => {
        node.put("token", System.currentTimeMillis())
        node.toString
      })
      .addSink(sink)

下面通过flink 的自定source、sink 实现,消费、生成kafka 数据的时候,获取数据的key ,和输出不同key的数据

思路: 使用kafka 原生的api,KafkaConsuemr和KafkaProducer 消费、生产kafka的数据,就可以获取到key值

kafka 生产者:

object KafkaKeyMaker {
  val topic = "kafka_key"
  def main(args: Array[String]): Unit =
首先,我们需要使用 Flink Kafka Consumer 从大主题中读取数据。然后,我们可以使用 KeyedStream 将数据按照 key 分组,然后使用 Flink Kafka Producer 将数据写入多个小主题。同时,我们也可以将数据写入 MySQL 数据库。下面是一个简单的示例程序: ```java import org.apache.flink.api.common.serialization.SimpleStringSchema; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer; import org.apache.flink.streaming.connectors.kafka.KafkaSerializationSchema; import org.apache.flink.streaming.connectors.kafka.KafkaSink; import org.apache.flink.streaming.util.serialization.KeyedSerializationSchema; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.serialization.StringSerializer; import java.util.Properties; public class KafkaSplitter { public static void main(String[] args) throws Exception { final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); // 从大主题中读取数据 Properties kafkaProps = new Properties(); kafkaProps.setProperty("bootstrap.servers", "localhost:9092"); kafkaProps.setProperty("group.id", "my-group"); FlinkKafkaConsumer<String> consumer = new FlinkKafkaConsumer<>("big-topic", new SimpleStringSchema(), kafkaProps); DataStream<String> stream = env.addSource(consumer); // 根据 key 分组 DataStream<String> keyedStream = stream.keyBy(line -> line.split(",")[0]); // 写入多个小主题 Properties producerProps = new Properties(); producerProps.setProperty("bootstrap.servers", "localhost:9092"); FlinkKafkaProducer<String> kafkaProducer = new FlinkKafkaProducer<>("small-topic", new SimpleStringSchema(), producerProps, KafkaSerializationSchema::get); keyedStream.addSink(kafkaProducer); // 写入 MySQL 数据库 keyedStream.addSink(new MySQLSink()); env.execute("KafkaSplitter"); } public static class MySQLSink extends RichSinkFunction<String> { private Connection connection; @Override public void open(Configuration parameters) throws Exception { super.open(parameters); Class.forName("com.mysql.jdbc.Driver"); connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "username", "password"); } @Override public void close() throws Exception { super.close(); if (connection != null) { connection.close(); } } @Override public void invoke(String line, Context context) throws Exception { String[] fields = line.split(","); String key = fields[0]; String value = fields[1]; PreparedStatement statement = connection.prepareStatement("INSERT INTO mytable (key, value) VALUES (?, ?)"); statement.setString(1, key); statement.setString(2, value); statement.executeUpdate(); } } } ``` 在上面的示例程序中,我们使用了 Flink Kafka Consumer 和 Flink Kafka Producer 来读取和写入 Kafka 主题。我们还实现了一个自定义的 MySQLSink,在其中将数据写入 MySQL 数据库。注意,我们需要将 MySQL 驱动程序添加到 Maven 依赖中。 ```xml <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.26</version> </dependency> ``` 使用这个程序,我们可以将一个大的 Kafka 主题拆分成多个小主题,并将数据写入 MySQL 数据库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值