Kafka ISR和offset小结

Kafka小结

使用Kafka的好处

  1. 解耦

    允许你独立的扩展或修改两边的处理过程,只要确保她们遵守同样的接口约束

  2. 可恢复性

    系统的一部分组件失效时,不会影响整个系统。并且即使一个处理消息的进程挂掉,新加入的消息也可以在系统恢复后被处理(通过每个消费者组对于主题保留的offset)

  3. 缓冲

    有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致问题。

  4. 去峰值&灵活

    能够使关键组件叮嘱突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃

  5. 异步通信

    允许用户把一个个消息放入队列而不立即处理(默认保留7天)。等需要的时候再处理它。

Kafka ISR机制

​ ISR是Kafka用来保证数据可靠性的机制,即保证每个分区都收到生产者生产的消息。

副本同步策略

​ Kafka的副本同步策略全部完成同步(默认,也可以设置别的),才发送ack(确认收到的响应)。即生产者将消息发送给某个topic的leader,leader要等待所有的follower同步完成才向生产者发送ack确认消息发布完成。这样所带来的优点就是集群规模减小了(对比zookeeper)数据冗余度低,但缺点是响应的延迟很高,因为要所有的分区都备份完成才返回ack。

​ack应答机制

Kafka提供了三种ack的级别,应对各种业务需求,用户可以综合数据的可靠性和延迟来考虑。

设置参数

acks=0|1|(-1|all)
  1. 0:producer 不等待broker 的ack,这一操作提供了一个最低的延迟,broker 一接收到还
    没有写入磁盘就已经返回,当broker 故障时有可能丢失数据
  2. 1:producer 等待broker 的ack,partition 的leader 落盘成功后返回ack,如果在follower
    同步成功之前leader 故障,那么将会丢失数据
  3. -1(all):全部分区同步完成再返回ack。但是如果follower同步完成后,broker发送ack之前,leader宕机,那么会造成重复数据

ISR

​ 前面提到,Kafka默认的副本同步策略是全部同步完成再返回ack。这样的效率是很慢的。于是提出了ISR机制。

​ ISR就是将维护所有副本同步完成,更改为了可以只维护一部分副本同步完成就向生产者返回ack,Leader发生故障后,新的leader也只会从ISR中选择。ISR里面维护着一个动态的分区队列,而里面的分区可以理解为服务状态较好的分区。那怎么来区分一个分区目前服务状态的好坏呢?

  • 和leader消息的差距(0.9.0版本就被移除了)

    replica.lag.max.messages
    

    即follower和leader间消息条数的差距。如果小于设定的数,就认为是好的,如果大于这个数,就会被踢出ISR队列。

    • 移除的原因
      • Kafka的消息生产是批处理形式的。假设我们将这个数设置为10.也就是Leader和Follower之间不能超过10条数据的差距。而大数据情景下,这个差距经常发生,也就造成了频繁的ISR的重写。而ISR是记录在Zookeeper中的,也会有相应的频繁Zookeeper交互,效率很低。
  • 和leader同步的延时

    #副本.延时.时间.最大.毫秒
    replica.lag.time.max.ms=10000
    

    当leader和follower之间通信的延迟小于设定的值时,就使其加入ISR队列,反之踢出ISR队列。

Kafka 的offset

​ Kafka把数据分类存储在一个个topic(主题)中,而每个主题都可以对应一个或多个分区。每个分区都有一个或者多个.log文件来存储真实的压缩后的数据,而每条数据都有自己的offset(偏移量)。消费者组中的每个消费者都会实时记录自己消费到哪个offset,以便于出错恢复时是从上一次的位置继续消费。offset就类似为索引,能很快定位到消息在.log文件中的位置。

(消费者组,主题,分区)三者唯一确定一个offset

offset存储的位置
  1. Zookeeper

    Kafka官方并不推荐使用这个方式存储offset,因为这会造成频繁的zookeeper读写,效率很低。

  2. Kafka自己开辟的一个特殊的topic

    拥有50个分区的特殊topic。

  3. 外部存储介质

    可以是MySQL、Redis等数据库。

offset的提交方式
  1. 自动提交

    有程序自身去提交offset,方便。

    enable.auto.commit=true # 开启自动提交offset
    auto.commit.interval.ms=100  # 自动提交的延迟
    
  2. 手动提交

    enable.auto.commit=false
    
    1. 同步提交

      当前线程会被阻塞知道offset提交成功

      consumer.commitSync();
      
    2. 异步提交

      consumer.commitAsync();
      

      不会阻塞当前线程,效率会高很多。

    自动提交offset很方便,但是脱离了掌控,往往会出现一些问题。

遇到的问题
  • 自动提交

    1. 我们要将Kafka中的数据处理后写入数据库,但是在我这次没写成功,但是offset已经提交完了,我就拿不到之前的数据了造成了数据泄露消费。----延迟低的时候
    2. 我们也将数据处理后写入数据库,写成功了,还没提交挂掉了。下次再运行的时候由于offset没变,造成了数据重复消费  ----延迟高的时候
  • 手动提交

    手动提交相对安全很多,不会有数据泄露消费的问题,但是极限情况下可能会有数据重复问题,但是这个问题配合自定义存储offset可以解决,比如配合mysql的事务,就能做到安全消费。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值