kafka的ISR机制保证了消息不会丢失。

        首先,要先清楚一个概念,什么是分区,什么是副本,什么是ISR。

        分区:在topic中分区就好比通往你家的道路是一条单行线,而现在引入分区就相当于把这条单行线改成了多通道道路。顺便说一句,由于消息是以追加到分区中的,多个分区顺序写磁盘的总效率要比随机写内存还要高(引用Apache Kafka – A High Throughput Distributed Messaging System的观点)这也是kafka高吞吐的保证!在kafka集群中创建topic的时候,kafka会在各个broker均匀分布分区。

        副本:副本是kafka高可用的前提。在分区中会有N个副本(n>0),而且副本分为领导副本和追随者副本。读写都在领导副本,追随者副本不对外服务,但是他会给领导副本发送请求从而和领导副本保持同步。

        生产者向topic发送消息时,topic每个分区都接受到消息时会向生产者反馈(ack),如果分区没接收到消息或者说分区没有像生产者反馈(ack)的话,生产者会重新发送消息(当然,这个是可以设置的)。在kafka中想要ack的话需要每个追随者副本都同步完成。当副本有N+1个的时候就可以容忍N个broker发生故障,保证kafka的高可用!

        但是这样又会引发新的性能问题,当某一个副本因为某种问题一直不能完成同步的时候,就会造成无法反馈ack。这时候就引入了一个新东西,就是ISR(In-Sync Replica)!

        现在不需要所有的追随者副本都和领导副本完成同步,只需要ISR集合里的副本和领导副本保持对齐即可!可是,这个样子还是会有上文中某一个副本因为某些问题无法完成对齐。所以,ISR可以配置一个东西(replica.lag.time.max.ms)当某一个副本同步时间超过了所配置的时间,ISR就会把该副本从集合当中踢掉。当领导副本不能正常工作的时候,kafka会从ISR集合中重新选取一个领导副本。此时ISR集合中所有副本都是和领导副本对齐的,所以不会造成消息的丢失。(当然,也可以选取不在ISR集合中的副本做为领导副本,可以进行配置)

        AR(Assigned Replicas),所有的副本统称AR。ISR是AR中的一个子集,有领导副本维护。当ISR集合中的追随者副本超过配置的阀值(包括延迟时间replica.lag.time.max.ms和延迟条数replica.lag.max.messages两个维度)kafka就会将该副本踢出ISR将其存储到OSR中。AR=ISR+OSR。

特性

        a.追随者副本不会对外提供服务,他会异步的和领导副本对齐。

       b.当ISR集合中的追随者副本与领导副本差距过大的时候领导着副本会将其踢出ISR集合,但是,如果该副本之后慢慢的追上了领导着副本他还是可以回到ISR集合中的。由此可见,ISR集合并不是静态不变的,而是有领导副本动态维护的。

       c.当ISR集合中的所有副本都ack之后领导副本才会commit。

       d.领导副本天然存在着ISR中,由此可见ISR中不是之后追随者副本。

        到现在大家应该就可以看出来ack是基于ISR的,保证了消息不丢失就会丢失吞吐量。上文中提到的生产者需要收到ack反馈才会进行下一步,这是可以设置的。

Properties props = new Properties();

props.put("bootstrap.servers", "localhost:9092");

props.put("acks", "0");

props.put("retries", 0);

props.put("batch.size", 16384);

props.put("key.serializer", StringSerializer.class.getName());

props.put("value.serializer", CustomerSerializer.class.getName());

producer = new KafkaProducer(props);

        0代表的是生产者不需要接收ack,无论领导者副本还是追随着副本是否数据落盘生产者都会继续下一步的操作

        1代表的是当领导者副本完成数据落盘的时候会响应ack,这样会保证领导节点内有一份数据,但是当追随者副本还未进行同步时领导者副本宕机会造成数据丢失

        -1代表的是需要领导副本和追随者副本都同步完毕才会响应ack。

                                                                                ps:延迟时间replica.lag.time.max.ms默认为10秒

相关阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。