Kafka 进阶学习(十八)—— 可靠性设置

216 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情

前言

今天是我 Kafka 学习的第 18 天,今天学习的内容是 Kafka 的可靠性设置。

就可靠性本身而言,它并不是一个可以用简单的“是”或“否”来衡量的一个指标,而一般是采用几个 9 来衡量的。任何东西不可能做到完全的可靠,今天我们就来看看 Kafka 的哪些设置能够最大程度地提高可靠性。

副本数量

就 Kafka 而言,越多的副本数越能够保证数据的可靠性,副本数可以在创建主题时配置,也可以在后期修改,不过副本数越多也会引起磁盘、网络带宽的浪费,同时会引起性能的下降。

一般而言,设置副本数为 3 即可满足绝大多数场景对可靠性的要求,而对可靠性要求更高的场景下,可以适当增大这个数值。

ack

我们再来看下 ACK 参数的三个可选值。

  • acks=1:· acks 的默认值即为 1。生产者发送消息之后,只要分区的 leader 副本成功写入消息,那么它就会收到来自服务端的成功响应。如果消息无法写入 leader 副本,比如在 leader 副本崩溃、重新选举新的 leader 副本的过程中,那么生产者就会收到一个错误的响应,为了避免消息丢失,生产者可以选择重发消息。acks 设置为 1,是消息可靠性和吞吐量之间的折中方案。
  • acks=0:生产者发送消息之后不需要等待任何服务端的响应。如果在消息从发送到写入 Kafka 的过程中出现某些异常,导致 Kafka 并没有收到这条消息,那么生产者也无从得知,消息也就丢失了。在其他配置环境相同的情况下,acks 设置为 0 可以达到最大的吞吐量。
  • acks=-1 或 acks=all:生产者在消息发送之后,需要等待 ISR(In-Sync Replicas,同步副本集) 中的所有副本都成功写入消息之后才能够收到来自服务端的成功响应。在其他配置环境相同的情况下,acks 设置为 -1(all) 可以达到最强的可靠性。但这并不意味着消息就一定可靠,因为 ISR 中可能只有 leader 副本,这样就退化成了 acks=1 的情况。

即对于 ack=-1 的配置,生产者将消息发送到 leader 副本,leader 副本在成功写入本地日志之后还要等待 ISR 中的 follower 副本全部同步完成才能够告知生产者已经成功提交,即使此时leader副本宕机,消息也不会丢失。同样如果在消息成功写入 leader 副本之后,并且在被 ISR 中的所有副本同步之前 leader 副本宕机了,那么生产者会收到异常以此告知此次发送失败。

消息发送模式

消息发送的 3 种模式,即发后即忘、同步和异步。对于发后即忘的模式,不管消息有没有被成功写入,生产者都不会收到通知,那么即使消息写入失败也无从得知,因此发后即忘的模式不适合高可靠性要求的场景。如果要提升可靠性,那么生产者可以采用同步或异步的模式,在出现异常情况时可以及时获得通知,以便可以做相应的补救措施,比如选择重试发送。

重试

有些发送异常属于可重试异常,比如 NetworkException,这个可能是由瞬时的网络故障而导致的,一般通过重试就可以解决。重试参数配置为 retries,默认情况下,retries 参数设置为 0,即不进行重试,对于高可靠性要求的场景,需要将这个值设置为大于 0 的值。

与 retries 参数相关的还有一个 retry.backoff.ms 参数,它用来设定 两次重试之间的时间间隔,以此避免无效的频繁重试。在配置 retries 和 retry.backoff.ms 之前,最好先估算一下可能的异常恢复时间,这样可以设定总的重试时间大于这个异常恢复时间,以此来避免生产者过早地放弃重试。如果不知道 retries 参数应该配置为多少,则可以参考 KafkaAdminClient,在 KafkaAdminClient 中 retries 参数的默认值为 5。

刷盘策略

在 broker 端还有两个参数 log.flush.interval.messages 和 log.flush.interval.ms,用来调整同步刷盘的策略,默认是不做控制而交由操作系统本身来进行处理。同步刷盘是增强一个组件可靠性的有效方式。

但是不建议设置成同步刷盘,原因是绝大多数情景下,一个组件(尤其是大数据量的组件)的可靠性不应该由同步刷盘这种极其损耗性能的操作来保障,而应该采用多副本的机制来保障。

手动提交消费位移

Kafka 的自动位移提交功能往往会带来重复消费和消息丢失的问题,对于高可靠性要求的应用来说显然不可取。

Kafka 中 enable.auto.commit 参数用来配置自动位移提交功能,默认值为 true,即开启自动位移提交的功能,虽然这种方式非常简便,但它会带来重复消费和消息丢失的问题,对于高可靠性要求的应用来说显然不可取,所以需要将 enable.auto.commit 参数设置为 false 来执行手动位移提交。

在执行手动位移提交的时候也要遵循一个原则:如果消息没有被成功消费,那么就不能提交所对应的消费位移。

回溯消费

对于消费端,Kafka 还提供了一个可以兜底的功能,即回溯消费,通过这个功能可以让我们能够有机会对漏掉的消息相应地进行回补,进而可以进一步提高可靠性。

参考文档

  • 《深入理解 Kafka:核心设计与实践原理》—— 朱忠华

往期文章