Kafka 是怎么工作的

2018/9/13 源自  CentOS

Kafka是由LinkedIn开发的一个分布式的消息系统,使用Scala编写,它以可水平扩展和高吞吐率而被广泛使用。目前越来越多的开源分布式处理系统如Cloudera、Apache Storm、Spark都支持与Kafka集成。

详细的 kafka 描述可以参考 浅谈 kafka

kafka节点之间如何复制备份的?
Kafka引入Partition的Replication之后,同一个Partition的就有了多个副本,把这些副本均匀的分布到多个Broker上,就保证了数据的安全,不再担心某个Broker宕机后使其中的Partition失效。
)

Partition没有Replication时,写入消息的逻辑很简单,现在有个多个副本,写消息时如何处理呢?
Kafka给多个Replication设置了一个Leader,其他副本叫做follower,Producer发送消息时,只发送给Leader,follower再从leader复制消息。

Kafka的消息复制思路比较独特,既不是同步复制,也不是完全的异步复制。同步复制非常安全,要求所有follower都复制完成才算是commit成功,但极大影响了吞吐率。完全异步复制的话性能很高,只要leader写入成功就算完成了,follower异步从leader进行复制,但安全性不好,数据丢失风险高。Kafka的Leader会看哪些follower的数据与自己是同步的,将其视为好同志,重点培养,放入一个列表,称为ISR(in-sync replica),当Leader收到新消息时,将消息发给列表成员,这些成员收到后,马上返回确认信息,Leader收到他们的确认后,就告诉 Producer消息已经提交成功。所以Kafka是采用了同步和完全异步的折中方式,让一部分高效的follower同步,让其他follower异步。

kafka消息是否会丢失?为什么?

消息丢失的场景

  • 网络异常
    acks设置为0时,不和Kafka集群进行消息接受确认,当网络发生异常等情况时,存在消息丢失的可能;

  • 客户端异常
    异步发送时,消息并没有直接发送至Kafka集群,而是在Client端按一定规则缓存并批量发送。在这期间,如果客户端发生死机等情况,都会导致消息的丢失;

  • 缓冲区满了
    异步发送时,Client端缓存的消息超出了缓冲池的大小,也存在消息丢失的可能;

  • Leader副本异常
    acks设置为1时,Leader副本接收成功,Kafka集群就返回成功确认信息,而Follower副本可能还在同步。这时Leader副本突然出现异常,新Leader副本(原Follower副本)未能和其保持一致,就会出现消息丢失的情况;

想要更高的吞吐量就设置:异步、ack=0;想要不丢失消息数据就选:同步、ack=-1策略

kafka的leader选举机制是什么?
leader在zk上创建一个临时节点,谁创建成功,谁就是 leader ,所有Follower对此节点注册监听,当leader宕机时,此时ISR里的所有Follower都尝试创建该节点,而创建成功者(Zookeeper保证只有一个能创建成功)即是新的Leader,其它Replica即为Follower。

kafka的消息保证有几种方式?

  • 如何保证数据的完全生产

ack机制:broker表示发来的数据已确认接收无误,表示数据已经保存到磁盘。
0:不等待broker返回确认消息
1:等待topic中某个partition leader保存成功的状态反馈
-1:等待topic中某个partition 所有副本都保存成功的状态反馈

  • 如何保证数据的完全消费

At-most-once(最多一次)

设置enable.auto.commit为ture
设置 auto.commit.interval.ms为一个较小的时间间隔.
client不要调用commitSync(),kafka在特定的时间间隔内自动提交。

At-least-once(最少一次)

设置enable.auto.commit为false
client调用commitSync(),增加消息偏移;

设置enable.auto.commit为ture
设置 auto.commit.interval.ms为一个较大的时间间隔.
client调用commitSync(),增加消息偏移;

Exactly-once(正好一次)

自己控制消息的offset,自己记录一下当前的offset,对消息的处理和offset的移动必须保持在同一个事务中,例如在同一个事务中,把消息处理的结果存到mysql数据库同时更新此时的消息的偏移。