Kafka——如何保证消息不丢失?

一.消费端丢失消息

我们知道消息在被追加到Partition的时候会被分配一个offset。offset表示当前消费的Partition的所在位置,Kafka通过offset可以保证消息在分区内的顺序性。当消费者拉取到分区的某个消息之后,消费者会自动提交offset。但是会出现一个问题:当消费者刚拿到这个消息准备的时候,突然挂掉了,消息实际上没有被消费,但是offset已经被自动提交了。

解决方法:关闭自动提交offset,每次在真正消费完消息之后再自己手动提交offset,每次在真正消费完消息后再自己手动提交offset。但是,这个会带来重复消费问题,自己需要保证幂等性。

二.Kafka丢失消息

我们知道为了分区引入了多副本机制。分区中的多副本之间有一个Leader,其他副本被称为Follower。我们发送的消息会到Leader副本,其他Follower副本会从Leader中拉取消息进行同步。生产者和消费者只与Leader交互,其他副本的存在只是为了保证消息存储的安全性。

加入Leader所在的Broker突然宕机,需要从Follower中重新选取一个Leader,但是Leader中的数据还有一些没有被Follower副本同步,这样的话,会造成数据丢失。解决方法取下:

  • acks=all(producer):默认为1,代表的是我们的消息只要被Leader接收才算发送成功。当设置为all的时候代表所有的副本都要接受到该消息之后该消息才算被成功发送
  • replication.factor>=3(topic):保证每个分区至少有3个副本,虽然造成数据冗余,但是带来了数据安全性
  • min.insync,replicas(服务端):这个参数必须大于1,这个是要求Leader至少感知至少有一个Follower与自己保持联系。为了保证Kafka的高可用,replication.factor必须大于min.insync,replicas,因为如果两个相等,这样挂掉一个副本,整个分区就无法工作
  • retires=max(producer):一旦写入失败,就无线重试
  • unclean.leader.election.enable=false:当Leader发生故障的时候就不会从Follower中和Leader同步程度达不到要求的副本中选举Leader,降低了消息丢失的可能性。

三.生产者丢失消息

Prodcuer调用send发送了消息之后,消息可能因为网络的问题并没有发送出去。所以我们不能默认调用send方法发送消息之后消息就是发送成功的。为了保证消息发送成功,我们需要判断发送的结果。在Kafka的API中就有这个回调函数的形式。

        ListenableFuture<SendResult<String, Object>> future = kafkaTemplate.send(topic, o);
        future.addCallback(result -> logger.info("生产者成功发送消息到topic:{} partition:{}的消息", result.getRecordMetadata().topic(), result.getRecordMetadata().partition()),
                ex -> logger.error("生产者发送消失败,原因:{}", ex.getMessage()));

还可以设置Producer的retires的次数,当出现网络问题之后能够自动重试消息发送,避免消息丢失。另外,还可以设置下重试的时间间隔。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值