kafka-消费者

问题:
1.位移越界原因?
2.kafka存储位移过期设置?

消费者组

消费者(Consumer)订阅kafka中的主题topic,从订阅主题拉取消息;
消费者组(group.id):每一个消费者属于一个消费者组,同一个主题的同一分区只能被一个消费者组中的一个消费者消费。让整体消费能力有横向伸缩性。
增加消费者组内消费者数量可以提高消费能力,但如果消费者组内消费者数量大于分区数,那么将有一个消费者分配不到任何分区而无法消费消息。

订阅主题和分区

1-集合订阅方式–AUTO_TOPICS
//按照topic订阅,如 subscribe(Arrays.asList(topic1,topic2))
void subscribe(Collection<String> topics);    
void subscribe(Collection<String> topics, ConsumerRebalanceListener listener);
2-正则表达式订阅方式–AUTO_PATTERN
//按照正则表达式订阅,如:subscribe(Pattern.compile("topic-*"))
void subscribe(Pattern pattern); 
void subscribe(Pattern pattern, ConsumerRebalanceListener listener);
3-指定分区订阅方式 --USER_ASSIGNED
void assign(Collection<TopicPartition> partitions);

//参数,表示主题和分区
public final class TopicPartition implements Serializable {
     private final int partition;
     private final String topic;
}

partitionsFor()

  //消费者获取主题的分区元数据
  List<PartitionInfo> partitionsFor(String topic);

  public class PartitionInfo {
    private final String topic;   //主题
    private final int partition;   //分区
    private final Node leader;  //leader所在位置
    private final Node[] replicas;  //AR集合
    private final Node[] inSyncReplicas;   // ISR集合
    private final Node[] offlineReplicas;   //OSR集合
 }
4-取消订阅
consumer.unsubscribe();
consumer.subscribe(new ArraysList<String>());
consumer.assign(new ArraysList<TopicPartition>());

消息消费

消息消费一般有两种方式:推和拉,kafka是拉模式,消息消费是一个不断轮询的过程,调用poll()方法。
分为按主题消费和按分区消费

// 在消费这的缓冲区没有可用数据时发生阻塞,设置值取决于对响应速度要求
public ConsumerRecords<K, V> poll(Duration timeout)

//按分区消费
List<ConsumerRecord<K, V>> records(TopicPartition partition);
//按主题消费
public Iterable<ConsumerRecord<K, V>> records(String topic);

public class ConsumerRecord<K, V> {
    private final String topic;  
    private final int partition;
    private final long offset;   //偏移量
    private final long timestamp;  时间戳
    private final TimestampType timestampType;  //时间戳类型
    private final int serializedKeySize;  //key序列化后的大小,没有则为-1
    private final int serializedValueSize;  //value序列化后的大小,没有则为-1
    private final Headers headers;
    private final K key;
    private final V value;
    private volatile Long checksum;  //CRC32的校验值
}

public enum TimestampType {
    NO_TIMESTAMP_TYPE(-1, "NoTimestampType"),
    CREATE_TIME(0, "CreateTime"),   //消息创建的时间戳
    LOG_APPEND_TIME(1, "LogAppendTime");  //消息追加到日志的时间戳
}

位移提交

偏移量(offset):对分区而言,每条消息都有唯一的offset,用来表示在分区中对应的位置。
位移(offset):对消费者而言,offset表示消费者消费到分区中某个消息的位置。
在旧消费者客户端,消费位移保存在zookeeper中;新消费者客户端中,消费位移保存在kafka内部主题_consumer_offsets中。
因为有了消费位移的持久化,才使消费者在关闭、崩溃或再均衡的时候可以继续消费,而不是重头消费。
消费位移是按照消费者组指定的。
提交位移是下一次要拉取的消息的偏移量,即已经消费消息的偏移量+1。

位移提交引起消息丢失和重复消费;

1.自动提交

kafka默认提交方式:
自动位移提交动作是在poll()方法的逻辑中完成的,在每次真正向服务端发起拉请求之前会检查是否可以进行位移提交,如果可以,就会提交上一次轮询的位移。

//默认自动提交
enable.auto.commit=true
//定期提交时间默认值是5秒
auto.commit.interval.ms
2.手动提交

1-同步位移提交

//只能提交当前批次对应的position值,
public void commitSync();
//每消费一条就提交一次位移可以用这个方法,但是会耗费性能,很少使用。
//可以按分区粒度同步提交消费位移
public void commitSync(Map<TopicPartition, OffsetAndMetadata> offsets)

2-异步位移提交
异步提交位移在执行的时候消费者线程不会被阻塞

public void commitAsync();
public void commitAsync(OffsetCommitCallback callback);
public void commitAsync(Map<TopicPartition, OffsetAndMetadata> offsets, OffsetCommitCallback callback);

异步提交失败重试会引起重复消费,所以需要设置一个递增的序号来维持异步提交的顺序。

控制或关闭消费

//暂停某分区在拉操作时返回数据给客户端
public void pause(Collection<TopicPartition> partitions) 
//恢复
public void resume(Collection<TopicPartition> partitions)
//返回被暂停的分区集合
 public Set<TopicPartition> paused()
 //调用后跳出poll()逻辑,抛异常WakeupException
 public void wakeup()

关闭及释放运行过程中占用的各种系统资源

//设置关闭方法最长执行时间
void close(Duration var1);
//默认30秒
void close();

指定位移提交

消费者组找不到位移的情况:
1.新创建消费者组的时候;
2.消费者组内一个新的消费者订阅了一个新的主题;
3.__consumer_offsets主题中有关这个消费者组的位移信息过期被删除时;
位移越界:知道消费位移但无法从实际的分区中找到。
重置消费位移:
找不到消费位移或者位移越界

auto.offset.reset    latest(默认)/earliest /none

seek()
seek()方法只能重置消费者分配到的分区的消费位移,而分区的分配是在poll()方法的调用中实现的,也就是说,在执行seek()方法之前需要先执行一次poll()方法,等分配到分区后才能重置消费位移。

public void seek(TopicPartition partition, long offset)
//获取消费者分区的方法
public Set<TopicPartition> assignment()

//无timeout则取request.timeout.ms  默认值30000
//获取指定分区末尾的消息位移
Map<TopicPartition, Long> endOffsets(Collection<TopicPartition> partitions);
Map<TopicPartition, Long> endOffsets(Collection<TopicPartition> partitions, Duration timeout);

//获取指定分区开始的消息位移
public Map<TopicPartition, Long> beginningOffsets(Collection<TopicPartition> partitions);
public Map<TopicPartition, Long> beginningOffsets(Collection<TopicPartition> partitions, Duration timeout);

//按照时间查询消息位移,返回值是大于等于timestampsToSearch的第一条时间戳
public Map<TopicPartition, OffsetAndTimestamp> offsetsForTimes(Map<TopicPartition, Long> timestampsToSearch);
public Map<TopicPartition, OffsetAndTimestamp> offsetsForTimes(Map<TopicPartition, Long> timestampsToSearch, Duration timeout);

再均衡

再均衡是指分区的所属权从一个消费者转移到另一个消费者的行为,它为消费组具备高可用和伸缩性提供保障,但是在再均衡发生期间,消费者组是无法读取消息的。
另外,当一个分区被重新分配到一个新的消费者,消费者当前状态会丢失,比如消费了某些消息还未提交位移,重新分配后会造成重复消费。

public interface ConsumerRebalanceListener {
    //再均衡开始前,消费者停止消费后调用,处理消费位移的提交
    void onPartitionsRevoked(Collection<TopicPartition> partitions);
    //重新分区后和开始消费前调用
    void onPartitionsAssigned(Collection<TopicPartition> partitions);

}

消费者拦截器

KafkaConsumer会在poll()方法返回之前调用onCommit()方法,对消息进行定制话操作;
KafkaConsumer会在提交完消费位移之后调用onCommit()方法

public interface ConsumerInterceptor<K, V> extends Configurable {
    ConsumerRecords<K, V> onConsume(ConsumerRecords<K, V> var1);
    void onCommit(Map<TopicPartition, OffsetAndMetadata> var1);
    void close();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值