kafka如何保证数据不丢失
bash
kafka是一个用来实现异步消息通讯的中间件,它的整个架构是由Producer和consumer和
broke来组成。
所以对于kafka保证消息不丢失的这个问题:可以从三个方面考虑来实现
1.producer端:需要确保消息能够到达Broker,并且是实现消息的存储;这时候有可能出现
网络问题,导致消息发送失败。所以针对Producer端可以通过两种方式来避免消息丢失:
1-1:produce默认是异步发送消息的;所以可以把异步发送改为同步发送,这样producer
就能实时知道消息发送的结果;
1-2:添加异步函数来监控发送的结果,如果失败,可以在回调中重试;
1-3:Producer本身提供了一个重试参数叫retries;如果因为网络问题或者Broker故障导致
发送失败,那么Producer会自动重试;
2.Broker端:Broker需要确保Producer发送的过来的消息是不会丢失的,只需要持久化到磁盘就
可以了。
但是Kafka为了提升性能采用了异步批量刷盘的实现机制:也就是说按照一定的消息量和时间间隔
去刷盘;而最终刷盘的动作是由操作系统来调度的;所以如果在刷盘之前系统崩溃了,就会导致数
据丢失;kafka并没有提供同步刷盘的一个实现机制;解决方法:需要通过Partition的副本机制
和acks机制来解决;
Partition的副本机制是针对每个数据分区的高可用策略,每一个Partition副本集会包含唯一
的一个leader和多个Follower。Leder专门处理事务类型的请求,而Follower负责同步Leader
的数据。那么在这样一个机制的基础上Kafka提供一个acks的参数,Producer可以去设置acks参数
去结合Borker的副本机制来共同保障数据的可靠性;acks这个参数的值有几个选择:
acks=0:表示producer不需要等待Broker的响应,就认为消息就发送成功了,这种情况就存在消息
丢失;
acks=1:表示Broker中leader Partition,收到消息之后,不等待其他的Follower Partition
的同步,就给Producer返回一个确认,这种情况下假设Leader Partition挂了,就会存在数据丢失;
acks=-1:表示Broker中的leader Partition收到消息之后,并且等待ISR列表中follower同步完成,
再去给Producer返回一个确认,那么这样一个配置可以保证数据的一个可靠性。
3.Consumer端:必须要能够消费这个消息;只要producer和broker的消息可靠性得到保障,消费者不太
可能出现消息无法消费的问题。除非消费者没有消费完这个消息就已经提交了这样一个offset。即便出现
这样一个问题可以重新调整offset的值来实现重现消费。
ka
kafka如何避免重复消费
bash
首先Kafka Broker上存储的消息都有一个Offset的标记,然后Kafka的消费者是通过Offset
这个标记来维护当前已经消费的数据。然后消费者每消费一批数据,kafka Broker就会更新OffSet
的一个值,避免重复消费的一个问题。
默认情况下,消息消费完成以后,会自动提交Offset这样一个值,避免重复消费。
1.kafak消费端自动提交的逻辑里面有一个默认5秒的间隔,也就是在5秒之后的下一次向Broker去获取消息
的时候来实现Offset的提交,所以在Consumer的消费过程中应用程序强制kill或者宕机的时候可能会导
致Offset没有提交。从而会产生重复消费的问题。
2.kafka里面有一个叫Partition Balance机制:就是把多个Partition均衡的分配个多个消费者。这时候
消费者端会从分配的Partition里面去消费消息。如果Consumer在默认的5分钟内没办法处理完一批信息的时
时候,就会触发Kafka的Rebalance的一个机制。从而导致Offset自动提交失败,而在重新Rebalance以后
消费者端还是从之前没有提交的Offset的位置开始去消费,从而导致重复消费的一个问题。
解决方案:
1.提高消费端的处理性能避免触发Balance;
可以用异步的方式来处理消息,缩短单个消息消费时长;
调整消息处理的超时时间;
减少一次性从Broker上拉取数据的条数;
2.可以针对消息生成md5然后保存到mysql或者redis里面,在处理消息之前先mysql或者redis里面判断是
否消费过(幂等性思想);
kafka消息队列怎么保证精准一次性和顺序消费?
bash
kafka的运行机制:当我们向某个Topic发送消息的时候,在kafka的Broker上会通过分区的机制,来
实现消息的物理存储。一个Topic可以有多个Partition,相当于把一个Topic里面的N个消费数据进行
一个分片存储,消费端去消费的时候会从指定的Partition里面去获取,在同一个消费组中,一个消费者
可以消费多个Partition里面的数据。但是消费者的数量只能小于等于Partition分区的数量。
AtMostOnce:消息投递至多一次,可能会丢但是不会重复;
AtLeastOnce:消息投递至少一次,可能会出现重复但不会丢;
ExactlyOnce:消息投递正好一次,不会出现重复也不会丢;
确保生产者只发生一次,消费端只接受一次;
生产者可以采用事务消息的方式,事务可以支持多分区的数据完整性和原子性;并且支持跨会话的ExactlyOnce的一个处理语义;即使生产者宕机重启,依旧能保持数据只处理一次;
开启事务首先需要开启幂等性;并设置enable.idempotence=true;然后对生产者的消息发送做事务控制,如果出现导致生产者重试的错误,这个消息只能写到kafka broker日志中一次;
虽然生产者能够保证在kafka broker上只记录唯一一条消息,但是由于网络延迟的存在,可能会导致Broker在
投递消息的时候触发重试导致投递多次,所以作为消费端可以采用幂等性的机制来避免重复消费的问题;
顺序消费:
在kafka里面,每个Partition分区的消息,本身就是按照顺序来存储的,只需要针对Topic设置一个Partition这样就可以保证所有消息都能够写入到Partition里面,而消费者这边只需要消费这个分区,就可以实现消息的顺序处理。