跳至主要內容

程序员小富大约 3 分钟

大家好,我是小富~

用过 Kafka 消息队列的同学可能都会遇到一件事,那就是消息丢失,这是我个人比较讨厌的一类线上问题,通常排查过程比较繁琐。要想防止出现这种丢失消息的情况,就需要我们在使用 kafka 的过程中开启一些特定配置,来尽量规避 kafka 消息丢失的风险。

kafka 架构图

我们先甩一张图看下 kafka 大致的架构图,这样你会更容易理解。kafka 它有三个主要的角色:consumer 消费者、broker 服务端、producer 生产者。

producer

回调通知

不要使用producer.send(msg),而要使用producer.send(msg, callback)。记住,一定要使用带有回调通知的send方法。

acks = all

设置acks = all。acks是Producer的一个参数,代表了你对“已提交”消息的定义。如果设置成all,则表明所有副本Broker都要接收到消息,该消息才算是“已提交”。这是最高等级的“已提交”定义。

retries

设置retries为一个较大的值。这里的retries同样是Producer的参数,对应前面提到的Producer自动重试。当出现网络的瞬时抖动时,消息发送可能会失败,此时配置了retries > 0的Producer能够自动重试消息发送,避免消息丢失。

Broker

unclean.leader.election.enable

设置unclean.leader.election.enable = false。这是Broker端的参数,它控制的是哪些Broker有资格竞选分区的Leader。如果一个Broker落后原先的Leader太多,那么它一旦成为新的Leader,必然会造成消息的丢失。故一般都要将该参数设置成false,即不允许这种情况的发生。

replication.factor

设置replication.factor >= 3。这也是Broker端的参数。其实这里想表述的是,最好将消息多保存几份,毕竟目前防止消息丢失的主要机制就是冗余。

min.insync.replicas

设置min.insync.replicas > 1。这依然是Broker端参数,控制的是消息至少要被写入到多少个副本才算是“已提交”。设置成大于1可以提升消息持久性。在实际环境中千万不要使用默认值1。

replication.factor > min.insync.replicas

确保replication.factor > min.insync.replicas。如果两者相等,那么只要有一个副本挂机,整个分区就无法正常工作了。我们不仅要改善消息的持久性,防止数据丢失,还要在不降低可用性的基础上完成。推荐设置成replication.factor = min.insync.replicas + 1。

Consumer

enable.auto.commit

确保消息消费完成再提交。Consumer端有个参数enable.auto.commit,最好把它设置成false,并采用手动提交位移的方式。就像前面说的,这对于单Consumer多线程处理的场景而言是至关重要的。

总结

通篇看下来你会发现,要实现 Kafka 的消息不丢失,似乎都得牺牲一定的效率。所以呢,是否要开启这些配置,必须得根据自身的业务类型来决定。比如说,对于支付类业务,慢点就慢点,没关系,资金安全才是重中之重,客户也能欣然接受。但要是秒杀类业务,其实是可以允许消息丢失的,大不了直接给用户提示没中奖就行,反正大家都是抱着试试看的心态。可要是系统卡顿,那用户可真的会骂娘哦!

参考文案

  • https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Kafka%E6%A0%B8%E5%BF%83%E6%8A%80%E6%9C%AF%E4%B8%8E%E5%AE%9E%E6%88%98/11%20%E6%97%A0%E6%B6%88%E6%81%AF%E4%B8%A2%E5%A4%B1%E9%85%8D%E7%BD%AE%E6%80%8E%E4%B9%88%E5%AE%9E%E7%8E%B0%EF%BC%9F.md

  • https://mp.weixin.qq.com/s/FhbW8l3zF6bMMqzn4xmwwg