kafka问题

1,769 阅读6分钟

1. Kafka是如何保障数据不丢失的?

kafka如何保障数据不丢失,也就是kafka提供了什么机制或者架构来保障数据的可靠性。

  • 分区副本架构
  • 数据复制同步

主要从以下三个方面概述

1.Topic 副本因子个数:replication.factor >= 3
2.同步副本列表(ISR):min.insync.replicas = 2
3.禁用unclean选举: unclean.leader.election.enable=false

1. 副本机制

  1. kafka的topic可以分为多个副本,该配置可以通过replication.factor实现。
  2. 副本类型可以分为领导者副本(leader )和追随者副本,每个分区在创建的时候,都会选举一个副本成为领导者副本,其它的默认成为跟随者副本。(依赖于zookeeper实现
  3. 只有leader 副本才会提供对外的服务,follower 副本是不会处理任务服务请求的,只是做数据同步,数据备份。
  4. 为了提高数据的可用性,副本一般会分布在不同的broker中,一般也建议把broker配置在不同的机架上,提高可用性。

2. ISR(In-sync replica):同步副本列表

  1. leader副本和与leader副本保持同步的follower副本均在ISR中。
  2. replica.lag.time.max.ms这是配置follower副本与leader副本同步的最长时间,如果在该时间内follower副本没有与leader副本同步,则会将该follower踢出ISR。
  3. 为了提高kafka的可靠性,我们一般需要将最小同步副本数量设置大一点,对于一个包含3 个副本的主题分区,如果min.insync.replicas=2 ,那么至少要存在两个同步副本才能向分区写入数据。 注意: 如果进行了上面的配置,此时必须要保证ISR中至少存在两个副本,如果ISR中的副本个数小于2,那么Broker就会停止接受生产者的请求。尝试发送数据的生产者会收到NotEnoughReplicasException异常,消费者仍然可以继续读取已有的数据。

3. 禁用unclean选举

  1. 选择一个同步副本列表中的分区作为leader 分区的过程称为clean leader election
  2. 非同步副本中选取一个副本作为leader的过程叫做unclean leader election
  • 开启unclean leader election这种方式进行选举leader,可以通过配置unclean.leader.election.enable进行设置。
  1. 开启的优点缺点:
  • 背景:因为ISR是动态的,所以存在ISR列表中为空的情况,在leader挂了,其它follower没有同步时,将会产生这种情况,而一旦发生这种情况,整个kafka将不能提供服务了。
  • 高可用-开启(比如实时点击流分析系统):为了kafka集群能够一直提供服务(优点),可以开启unlean.leader选举,但是因为选举的是非ISR列表中的follower作为新的leader,因为这些follower上的信息可能与之前的leader上的数据相差比较大,那么新选举的follower成为leader后,因为没有同步老leader上的数据,就会产生数据丢失的情况(缺点)
  • 数据一致性-禁用unclean选举(应用:比如银行,要去数据一致性高):禁用的话,那么选举leader只能从ISR中选举,这样可以可以保障数据的一致性(当然,这个一致性不能完全保障,因为follower中的数据是异步和leader同步的,如果数据没有同步完,leader就挂了,那么新选举的leader里面因为没有完全同步老leader数据,就会存在数据部分丢失的可能性。除非设置里acks=all,确保了所有follower全部同步了leader,并响应给producer
follower和leader数据同步和如下两个参数关系密切:

replica.lag.time.max.ms:同步副本滞后与leader副本的时间
zookeeper.session.timeout.ms:与zookeeper会话超时时间

2. 如何解决kafka数据丢失问题?

  • acks=all:所有副本同步后
  • 配置 retries > 0 的 Producer 能够自动重试消息发送,避免消息丢失。
  • 配置auto.offset.reset,这个参数有两种配置。一种是earliest:消费者会从分区的开始位置读取数据,不管偏移量是否有效,这样会导致消费者读取大量的重复数据,但可以保证最少的数据丢失。一种是latest(默认),如果选择了这种配置, 消费者会从分区的末尾开始读取数据,这样可以减少重复处理消息,但很有可能会错过一些消息。

补充让kafka数据不丢失

  • 不要使用 producer.send(msg),而要使用 producer.send(msg, callback)。
  • 设置 acks = all (确保所有follower都同步数据完成在响应producer)
  • 设置 retries 为一个较大的值。(当producer发送消息失败,多尝试重新发送消息)
  • 设置 unclean.leader.election.enable = false。(禁用非同步follower参与竞选leader)
  • 设置 replication.factor >= 3。(配置分区副本数大于等于3)
  • 设置 min.insync.replicas > 1。(配置可用ISP同步副本数大于1)
  • 确保 replication.factor > min.insync.replicas。(分区副本数大于可以同步副本数配置) 这个和上面的推断结果差不多。

3. kafka可以保障永久不丢失数据吗?

Kafka 只对“已提交”的消息(committed message)做有限度的持久化保证

    1. 已提交:就是数据已经记录在log文件中的数据,kafka响应给producer,数据已经接收成功的数据(acks=1,或者acks=all)
    1. 这些消息的日志文件所在的broker是正常的
  • 所以总而言之,kafka是可以做到保障永久不丢失数据的,只不过要有条件限制

4. 如何保障kafka中的消息是有序的?

  1. kafka是分区有序的,如果一个主题有多个分区,那么Kafka会按照key将其发送到对应的分区中,所以,对于给定的key,与其对应的record在分区内是有序的。 方案一: 对于需要保障消息有序的topic,设置单个分区,但是会影响吞吐量。

方案二: 设置两个参数:

  • 消息发送失败是,重试次数,配置retries>0,还需要配置max.in.flight.requests.per.connections:1,该参数是保障消息写入的顺序,当尝试重发第一批消息的时候,就不会有其他消息尝试发送给broker。这种也会影响吞吐量,但是可以保障消息是顺序发送的。

5. 如何确定kafka分区的数据量?

一个简单的计算公式为:分区数 = max(生产者数量,消费者数量)

生产者数量=整体生产吞吐量/每个生产者对单个分区的最大生产吞吐量

消费者数量=整体消费吞吐量/每个消费者从单个分区消费的最大吞吐量

选择合适的分区数量可以达到高度并行读写和负载均衡的目的,在分区上达到均衡负载是实现吞吐量的关键。需要根据每个分区的生产者和消费者的期望吞吐量进行估计。

6. 重新平衡kafka集群?

在下面情况发生时,需要重平衡集群:

  • 主题分区在整个集群里的不均衡分布造成了集群负载的不均衡。
  • broker离线造成分区不同步。
  • 新加入的broker 需要从集群里获得负载。 使用kafka-reassign-partitions.sh命令进行重平衡

7. 如何查看消费组是否存在滞后消费?

备注:

参考如下

  1. kafka-问题
  2. java小咖秀