1、分区策略: 1)分区的原因: (1)方便在集群中扩展,每个partition可以通过调整以适应它所在的机器,而一个topic又可以由多个partition组成,因此整个集群就可以适应任意大小的数据了。 (2)可以提高并发,因为可以以partition为单位进行读写了。
2)分区的原则:  (1)在指出了partition的情况下,直接将指明的值作为partition的值。 (2)没有指明partition值但是有key的情况下,将key的hash值与topic的partition数进行取余得到partition值。 (3)既没有指明partition值又没指出key的情况下,使用轮询算法。第一次加入的分区是随机的,后面进行轮询。
2)保证数据的可靠性 为了保证生产者发送的数据,能可靠地发送给指定的topic,Topic的每个partition收到生产者发送的数据后,都需要向生产者发送一个ack(确认收到),如果生产者收到ack就会进行下一轮的数据发送,否则就会重新发送该数据。  这里又会衍生出以下两个问题 (1)何时发送ack:当确保有follower和leader同步完数据后,leader才能发送ack,这样才能保证leader挂了之后数据的安全性。
(2)有多少follower同步完成后,leader才发送ack呢?全部的follower都同步完成吗?部分follower同步完成?  kafka选择了第二种方案,全部的follower同步完成才会让leader发送ack。因为,第一种方案为了容忍n台节点的故障需要维护2n+1个副本,而第二种方案只需要维护n+1台副本。kafka的每个分区都会有大量数据,第一种方案会造成大量数据的冗余。第二种方案可能会造成网络延迟,但是网络延迟对kafka来说影响较小。
ISR 采用第二种方案后,设想以下的场景:leader收到数据,follower开始同步数据,但是有一台或几台follower发送故障,无法同步完成,这样leader就不能发送ack给生产者。这个问题怎么解决?
Leader维护了一个动态的ISR,意为与leader保持同步的follower集合。当ISR中的follower完成数据同步后,Leader就会给生产者发送ack。如果follower长时间未和leader同步数据,leader就会将该follower踢出ISR的队伍,该时间阈值由replica.lag.max.ms参数设定。leader发生故障后会从ISR集合中选出新的leader.
ack应答机制: 对于某些不太重要的数据,对数据的可靠性要求不太高,所以没必要等ISR中的follower全部同步完。kafka为用户提供了三种可靠性级别,根据用户对可靠性和延迟的要求进行权衡,选择配置。
ack参数配置: acks的参数可以设置为“0”,“1”,“-1”。
0::生产者不需要等待broker的ack,broker一接收到还没有写入磁盘就已经返回,当broker故障时可能丢失数据。就是生产者直接发送数据,不需要接受返回的ack。
1::生产者等待broker的ack,partition的leader落盘成功后返回ack,如果follower在同步成功之前,leader发送故障,那么将会丢失数据。
-1::生产者等待broker的ack,partition的leader和follower全部落盘成功后才会返回ack.如果在follower同步完成后,broker发送ack之前,leader发送故障,那么会造成数据重复。
|