数据可靠:
Kafka在将数据通过sender线程发往Broker集群之后,会等待每一个请求的ack。ack应答有三种级别
- 0:生产者发送过来的数据,不需要等待数据落盘应答
- 1:生产者发送过来的数据,Leader收到数据落盘后应答
- -1(all):生产者发送过来的数据,Leader+isr队列中所有节点收齐数据落盘后应答。
可靠性分析:
- 0:丢数,生产者发送数据到Leader上,数据还没落盘,Leader挂了,导致数据丢失。
- 1:丢数:生产者发送数据到Leader上,数据在Leader上落盘,回复ack。在集群还未同步时,Leader挂了,重新选举产生Leader,此时这个Leader上是没有上一条数据的,而同步之后,集群中就完全丢失了上一条数据。
- -1:正常情况下不会发生丢数,但是由于一个节点挂了,导致集群无法正常运转下去,这时就涉及到ISR了。Leader维护了一个动态的in-sync replica set(ISR),意为和Leader保持同步的Follower和Leader的集合。如果Follower长时间未向Leader发送通信请求或同步数据,则将Follower踢出ISR。默认30s。这样就不用等长时间联系不上或者已经故障的节点了。这样就解决了运行问题。但是,特殊的情况下,集群还是有可能发生丢数的风险:如果分区副本设置为1,或者ISR中应答的最小副本数设置为1(默认1),这样的话,和ack=1的效果是一样的,任有丢数的风险。
那么到底有没有完全可靠的情况呢?答案是有的。
- 数据完全可靠条件:ACK级别设置为-1 + 分区副本数大于等于2 + ISR中应答的最小副本数大于等于2
可靠性总结:
- acks=0,生产者发送过来数据就不管了,可靠性差, 效率高;
- acks=1,生产者发送过来数据Leader应答,可靠性中等,效率中等;
- acks-1,生产者发送过来数据Leader和ISR队列里面所有Follower应答,可靠性高,效率低; 在生产环境中,acks=0很少使用;acks=1,一般用于传输普通日志,运行丢失个别数据;acks=-1,一般用于传输和钱相关的数据,对可靠性要求比较高的场景。
数据重复:
acks:-1,生产者发送过来数据,Leader接收并落盘,Follower接收并落盘。在还有Follower未同步数据完成时,Leader挂了,重新选举Leader,而新的Leader恰好是落盘成功的Broker之一。这时生产者觉得上一条消息未发送成功,会再发送一次,这样就导致了数据重复。也就是说,数据完全可靠条件只能保证至少一次成功发送。
- 至少一次(At Least Once) = ACK级别设置为-1 + 分区副本大于等于2 + ISR中应答最小副本数量大于等于2。保证数据不丢失,但是不能保证数据不重复。
- 最多一次(At Most Once)= ACK级别设置为0。保证数据不重复,但是不能保证数据不丢失。
那么怎么实现精确一次呢?
- 精确一次(Exactly Once )Kafka在0.11版本之后,引入了一项重大特性:幂等性和事务。幂等性就是指Producer不论向Broker发送多少重复数据,Broker端都只会持久化一条,保证了不重复。- 精确一次(Exactly Once):幂等性 + 至少一次(ack=-1 + 副本数>=2 + ISR 中最小副本数量>=2)
重复数据的判断标准:具有<PID,Partition,SeqNumber>相同主键消息提交时,Broker只会持久化一条。其中PID是Kafka每次重启都会分配一个新的;
Partition表示分区号;Sequence Number是单调自增的。所以幂等性只能保证的是在单分区单会话内不重复。而关于更高级的涉及到多会话或者客户端重启问题,就需要由事务来解决了。这里就不过多的介绍了。
版权归原作者 cluse_ld 所有, 如有侵权,请联系我们删除。