kafka等mq基本组成元素是 Producer Broker Consumer三部分,所以针对消息不丢失、不重复也是从这三方面来解答
消息丢失测试策略
1 Producer
Kafka Producer发送完消息时,通过ack来控制消息的确认机制。
ack=0 此时producer发送完消息就不管了,也不等待broker端响应,此种情况容易造成消息丢失
ack=1 broker分为leader节点+follower节点,ack=1时,只要leader节点收到消息就会给生产者确认,这时如果follower节点消息还没有同步但leader节点就挂了就会造成消息丢失
ack=-1(或者all) 此时需要leader+follower节点都都受到消息后才给消费者确认。这可以保证消息不丢失,但吞吐量会降低
2 Broker
kafka broker端通过副本机制保证消息的可靠性。每个分区都有一个Leader+n个Followers。生产者发送消息到Leader后消息都会sync到follower,当leader挂掉后,会从followers中选举一个作为leader
3 Consumer
consumer端消息不丢失是从其消息提交方式来保证的
Consumer端消息提交方式分为:自动提交和手动提交。
默认情况下是自动提交,这样consumer在消费消息时会定时向broker提交自己的offset,但这样如果消费者在消费消息时挂掉了,这时如果没有提交offset或者提交了offset但消息没有消费完就会造成消息重复消费或者消息丢失情况。我们可以采用手动提交的方式提交当前offset,只需要在代码中保证事务性,只有消息成功消费处理之后再手动提交offset,这样就能保证消息不丢失和不重复消费
4 最终一致性
除了上边方式保证消息不丢失外,在对强一致性要求不高的系统,可以采用最终一致性保证消息不丢失。比如在produer端发送完所有消息,同时consuer消费完之后的某一时刻,从producer端发送之前发送所有消息的recon信息,consumer端消费这些recon信息和之前消费信息进行对比判断是否有消息丢失,如果有消息丢失则把这些丢失的消息返回给producer端,让producer端重新发送一便
kafka消息重复消费
1. Producer端为每条消息生成一个唯一ID,并且在消费端消费数据是对这个ID进行判断
2. 幂等性消费者
在kakfa0.11版本之后都支持幂等消费者,producer端通过对每条发送的消息生成一个ProducerId+sequence Number保证即使消息重发也不会出现重复消息问题。不过这只能保证单分区内消息不重复,跨分区情况下还是需要事务机制
3 事务
Kafka事务和Redis事务大体类似,都是将多个记录作为一个原子性操作一起发送,要么全部成功要么全部失败。Kafka事务实现是在Producer端来操作的,在consumer端不做事务操作;可以通过设置enable.idempotence=ture和transaction id来实现
3.1 kafka事务流程
初始化事务生产者
producer.initTransacitons();
开启事务
producer.beginTransaction();
发送消息集合
producer.send(new ProducerRecord<>("topic1","key1","value1"));
producer.send(new ProducerRecord<>("topic1","key2","value2"));
...
提交事务/回滚事务
producer.commitTransaction(); //或者producer.aboartTransaciton();
3.2 Kafka 事务的特点与保证
原子性
在一次事务中,producer发送的消息集合要么都提交成功,要么全部都失败;
在事务提交成功前,所有消息都看不见
幂等性
避免消息重复写入
隔离性
kafka使用读已提交,未提交或者终止的事务消息都不会暴漏给消费者
3.3 Kafka Producer正确事务流程
注意必须写try-catch 包住整个事务过程,出错就aboartTransaction()

4. 消费端去重
4.1 利用数据库唯一主键去重
4.2 布隆过滤器去重(https://www.cnblogs.com/enhance/p/18915026)
布隆过滤器可以存储已处理消息的hash值,查询时可以快速判断一条消息是否被处理过
参考文献:
https://mp.weixin.qq.com/s/u5tPmYM0TyaKyDBU2lpj2Q
浙公网安备 33010602011771号