在Flink中提供了特殊的Connectors从kafka中读写数据,它基于Kafka Consumer API以及Producer API封装了自己的一套API来连接kafka,即可读取kafka中的数据流,也可以对接数据流到kafka中,基于kafka的partition机制,实现了并行化数据切片。下面让我们来看看它的主要API以及使用。
使用kafka-connector还需要导入单独的依赖包,它对应着不同版本的kafka,下面这张表是kafka-connector的不同版本的AP以及区别。
Flink kafka Consumer的API类继承图如下:
在其中一个版本的API为例,我们看一下其构造函数:
FlinkKafkaConsumer010(String topic, DeserializationSchema valueDeserializer, Properties props)
FlinkKafkaConsumer010(String topic, KeyedDeserializationSchema deserializer, Properties props)
FlinkKafkaConsumer010(List topics, DeserializationSchema deserializer, Properties props)
FlinkKafkaConsumer010(List topics, KeyedDeserializationSchema deserializer, Properties props)
FlinkKafkaConsumer010(Pattern subscriptionPattern, KeyedDeserializationSchema deserializer, Properties props)
这里主要有三个构造参数:
当我们从kafka中消费数据的时候,就需要反序列化操作,因此Flink提供了反序列化操作的接口DeserializationSchema/KeyedDeserializationSchema,后者的区别是带有key,以下是几种常用的反序列化schema:
代码示例如下:
Properties properties = new Properties();
properties.setProperty("bootstrap.servers", "localhost:9092");
// only required for Kafka 0.8
properties.setProperty("zookeeper.connect", "localhost:2181");
properties.setProperty("group.id", "test");
DataStream stream = env
.addSource(new FlinkKafkaConsumer08<>("topic", new SimpleStringSchema(), properties));
Flink kafka consumer的消费模式设置
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
FlinkKafkaConsumer08 myConsumer = new FlinkKafkaConsumer08<>(...);
myConsumer.setStartFromEarliest(); // start from the earliest record possible
myConsumer.setStartFromLatest(); // start from the latest record
myConsumer.setStartFromTimestamp(...); // start from specified epoch timestamp (milliseconds)
myConsumer.setStartFromGroupOffsets(); // the default behaviour
DataStream stream = env.addSource(myConsumer);
如何保证其容错性呢?
我们可以通过checkpoint的方式来保证,如果Flink启用了检查点,Flink Kafka Consumer将会周期性的checkpoint其Kafka偏移量到快照。如果作业失败,Flink将流程序恢复到最新检查点的状态,并从检查点中存储的偏移量开始重新消费Kafka中的记录。
Flink Kafka Consumer offset提交行为:
Flink还支持动态分区的发现,即当我们需要扩充集群或者缩减集群规模的时候,kafka的partition可能会发现改变,我们并不需要重启Flink就可以保证数据被完整消费以及负载均衡,并且保证消费的exactly-once语义。
默认禁止动态发现分区,把flink.partition-discovery.interval-millis设置大于0即可启用:properties.setProperty(“flink.partition-discovery.interval-millis”, “30000”)
。
Flink kafka producer API的类继承关系图如下:
其主要构造函数如下:
FlinkKafkaProducer010(String brokerList, String topicId, SerializationSchema serializationSchema)
FlinkKafkaProducer010(String topicId, SerializationSchema serializationSchema, Properties producerConfig)
FlinkKafkaProducer010(String brokerList, String topicId, KeyedSerializationSchema serializationSchema)
FlinkKafkaProducer010(String topicId, KeyedSerializationSchema serializationSchema, Properties producerConfig)
FlinkKafkaProducer010(String topicId,SerializationSchema serializationSchema,Properties producerConfig,@Nullable
FlinkKafkaPartitioner customPartitioner)
FlinkKafkaProducer010(String topicId,KeyedSerializationSchema serializationSchema,Properties
producerConfig,@Nullable FlinkKafkaPartitioner customPartitioner)
其构造函数的参数与上面consumer的类似,这里不再赘述。这里简单介绍一下FlinkKafkaPartitioner
,默认的是FlinkFixedPartitioner
,即每个subtask的数据写到同一个Kafka partition中。我们还可以自定义分区器,继承FlinkKafkaPartitioner(partitioner的状态在job失败时会丢失,不会checkpoint)。
FlinkKafkaProducer的容错性保证:
Kafka 0.8:
at most once(有可能丢数据)
Kafka 0.9/0.1:
Kafka 0.11: