kafka消费者
1、消费方式
consumer采用pull(拉)模式从broker端读取数据。(push(推)模式很难适应消费速率不同的消费者,因为消息的发送速率是由broker端决定的)
pull的缺点:当kafka中没有数据时,消费者将处于死循环,一致返回空数据。针对这一点,kafka的消费者在消费数据时需要指定超时时间(timeout)。
2、分区分配策略
一个consumer group(消费者组)中包含多个consumer,一个topic有多个partition,所以必然会涉及到partition的分配问题,即确定哪个partition由哪个consumer来消费。
同一个消费者组中的消费者,同一时刻是只能有一个消费者消费,不同的消费者组可以同时消费同一个分区。
kafka中有两种分配策略:RoundRobin(轮询)、RangeAssigonr。
RoundRobin:将consumer group中订阅的所有主题当成一个主题后,进行分区排序(这样同一个主题的分区可能不在一起)之后,来进行轮询。
举例:(1)、同一个consumer group中,有两个消费者A、B,其中A订阅了主题T1,T2,B订阅了主题T2,T3,当进行轮询时,可能出现B消费者消费了T1中的数据,A消费者消费了T3中的数据。
(2)、同一个consumer group中,有两个消费者A、B,其中A订阅了主题T1,B订阅了主题T2,当进行轮询时,可能出现B消费者消费了T1中的数据,A消费者消费了T2中的数据。
因此RoundRobin策略必须保证同一个consumer group中的消费者必须订阅相同的topic。
RangeAssigonr(kafka默认的策略):按照消费者总数和分区总数进行整除运算来获得一个跨度,然后将分区按照跨度进行平均分配,以保证分区尽可能均匀地分配给所有的消费者。对于每一个topic,该策略会将内consumer group中所有订阅这个topic的消费者按照名称的字典序排序,然后为每个消费者划分固定的分区范围,如果不够平均分配,那么字典序靠前的消费者会被多分配一个分区。
假设n=分区数/消费者数量,m=分区数%消费者数量,那么前m个消费者每个分配n+1个分区,后面的(消费者数量-m)个消费者每个分配n个分区。
因此在随着consumer group中订阅的主题增多,消费者之间消费的分区数差距会增大,也就是消费者之间消费数据不对等。
当consumer group里面的消费者发生变化时,将会触发分区分配策略。
3、offset的维护
由于consumer在消费过程中可能出现断电宕机故障,consumer恢复后,需要从故障前的位置接着消费,这个是就需要用到offset了。
offset是根据consumer group+topic+partition确定的。
(老版本(0.9之前)offset存储在zookeeper中:/consumers/消费者组/offset/topic名称/partition(分区号);新版本存储在kafka本地的topic中:__consumer_offsets(50个分区))
读取__consumer_offsets的数据
(1)、修改配置文件consumer.properties
#是否排除内部的主题
exclude.internal.topics=false
(2)读取offset
0.11.0.0之前版本
bin/kafka-console-consumer.sh --topic __consumer_offsets --zookeeper localhost:2181 --formatter
"kafka.coordinator.GroupMetadataManager\$OffsetsMessageFormatter" --consumer.config config/consumer.properties --from-beginning
0.11.0.0之后版本(含)
bin/kafka-console-consumer.sh --topic __consumer_offsets --zookeeper localhost:2181 --formatter
"kafka.coordinator.group.GroupMetadataManager\$OffsetsMessageFormatter" --consumer.config config/consumer.properties --from-beginning
(3)、获取consumer group的group id(后面需要根据该id查询它的位移信息)
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092,localhost:9093,localhost:9094 --list --new-consumer

(4)、计算指定consumer group在__consumer_offsets topic中分区信息
这时用到了上面的group.id(本例中是console-consumer-50059)。Kafka会使用下面公式计算该group位移保存在__consumer_offsets的哪个分区上:
Math.abs(groupID.hashCode()) % numPartitions
本例中:Math.abs("console-consumer-50059".hashCode()) % 50=10
(5)、获取指定consumer group的位移信息
0.11.0.0版本之前
bin/kafka-simple-consumer-shell.sh --topic __consumer_offsets --partition 11 --broker-list localhost:9092 --formatter
"kafka.coordinator.GroupMetadataManager\$OffsetsMessageFormatter"
0.11.0.0版本以后(含)
bin/kafka-simple-consumer-shell.sh --topic __consumer_offsets --partition 11 --broker-list localhost:9092
--formatter "kafka.coordinator.group.GroupMetadataManager\$OffsetsMessageFormatter"

浙公网安备 33010602011771号