1.1 Kafka背景
最初由Linkedin 开发的分布式消息中间件现已成为Apache顶级项目
- Broker:Kafka中指部署了Kafka实例的服务器节点
- Topic:用来区分不同类型信息的主题
- Partition:每个topic可以有一个或多个partition(分区)。分区是在物理层面上的,不同的分区对应着不同的数据文件。Kafka使用分区支持物理上的并发写入和读取,从而大大提高了吞吐量
- Record:实际写入Kafka中并可以被读取的消息记录。每个record包含了key、value和timestamp
- Producer:生产者,用来向Kafka中发送数据(record)
- Consumer:消费者,用来读取Kafka中的数据(record)
- Offset( 生产offset,消费offset,offset lag):offset lag是kafka消费数据和生产数据的距离偏移量,在0.8版本的时候记录在zk里面,0.9开始用特定的topic来记录
- Consumer Group:为了区分不同消费者消费数据的偏移量,提出了消费者组概念,相同消费组会改变相同的偏移量
1.2 引入依赖
Flink读取kafka数据需要通过maven引入依赖:
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-kafka-0.10_2.11</artifactId>
<version>1.6.2</version>
</dependency>
1.3 Flink KafkaConsumer
Flink KafkaConsumer目前已经出现了4个大的版本:FlinkKafkaConsumer08、FlinkKafkaConsumer09、FlinkKafkaConsumer10和FlinkKafkaConsumer11.
FlinkKafkaConsumer010构造器如下:
- 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)
三个构造参数:
- 要消费的topic(topic name / topic names/正表达式)
- DeserializationSchema / KeyedDeserializationSchema(反序列化Kafka中的数据)
- Kafka consumer的属性,其中三个属性必须提供:
- bootstrap.servers (逗号分隔的Kafka broker列表)
- zookeeper.connect (逗号分隔的Zookeeper server列表) (仅Kafka 0.8需要)
- group.id(consumer group id)
反序列化Schema
作用:对kafka里获取的二进制数据进行反序列化并转换成Java/Scala对象。DeserializationSchema定义了该转换模式,通过T deserialize(byte[] message)来实现。
反序列化Schema类型(接口):
DeserializationSchema(只反序列化value)
public interface DeserializationSchema<T> extends Serializable, ResultTypeQueryable<T> {
T deserialize(byte[] var1) throws IOException;
boolean isEndOfStream(T var1);
}
KeyedDeserializationSchema
public interface KeyedDeserializationSchema<T> extends Serializable, ResultTypeQueryable<T> {
T deserialize(byte[] msgKey, byte[] msg, String topic, int partition, long offset) throws IOException;
boolean isEndOfStream(T var1);
}
常见反序列化Schema:
- SimpleStringSchema:字符串反序列化器
- JSONDeserializationSchema / JSONKeyValueDeserializationSchema:JSON反序列化器
- TypeInformationSerializationSchema/ TypeInformationKeyValueSerializationSchema(适合读写均是flink的场景)
- AvroDeserializationSchema
1.4 FlinkKafkaConsumer010 简样版代码
FlinkKafkaConsumer消费模式设置(影响从哪里开始消费)
设置FlinkKafkaConsumer消费模式示例代码如下所示:
不同消费模式的解释如下所示:
auto.offset.reset 的值为:earliest,latest(默认),和none
- 如果存在offest时,不管设置为earliest 或者latest 都会从已经提交的offest处开始消费
- 如果不存在已经提交的offest时,earliest 表示从头开始消费,latest 表示从最新的数据消费,也就是新产生的数据.
- none topic各分区都存在已提交的offset时,从提交的offest处开始消费;只要有一个分区不存在已提交的offset,则抛出异常
- 注意:当作业从故障中恢复或者从savepoint还原时,上述设置的消费策略将不能决定开始消费的位置,真正的起始位置由savepoint或checkpoint中存储的偏移量。
Checkpoint启动设置:
如果Flink启用了检查点,Flink Kafka Consumer将会周期性的checkpoint其Kafka偏移量到快照。通过实现CheckpointedFunction,数据保存到一个叫做 ListState<Tuple2<KafkaTopicPartition, Long>> 。保证仅一次消费。
Flink Kafka Consumer Offset提交行为分为以下两种:
不同情况下消费起始位置的分析
总结思路:
动态Topic discovery 和 动态Partition discovery(比如以前kafka3个分区消费能力低,现在改成4个)
Flink Kafka Consumer支持动态发现Kafka Topic,仅限通过正则表达式指定topic的方式。
默认禁止动态发现分区,把flink.partition-discovery.interval-millis设置大于0即可启用。
Flink Kafka Consumer支持动态发现Kafka分区,且能保证exactly-once。
默认禁止动态发现分区,把flink.partition-discovery.interval-millis设置大于0即可启用:
1.5 Flink KafkaProducer
FlinkKafkaProducer包含了如下不同的构造方法:
- 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)
参数:
序列化接口SerializationSchema:
- byte[] serialize(T element);
序列化接口KeyedSerializationSchema: - byte[] serializeKey(T element);
- byte[] serializeValue(T element);
- String getTargetTopic(T element)
常见的序列化Schema: - TypeInformationSerializationSchema/ TypeInformationKeyValueSerializationSchema(适合读写均是flink的场景)
- SimpleStringSchema
producerConfig:
- FlinkKafkaProducer内部KafkaProducer的配置 https://kafka.apache.org/documentation.html
FlinkKafkaPartitioner:
- 默认使用FlinkFixedPartitioner,即每个subtask的数据写到同一个Kafka partition中。
自定义分区器:继承FlinkKafkaPartitioner(partitioner的状态在job失败时会丢失,不会checkpoint)。