Kafka:是有很多小消息还是更少但更大的消息更好?
Kafka: is it better to have a lot of small messages or fewer, but bigger ones?
有一个微服务,从外面接收一批消息,推送到kafka。每条消息都是单独发送的,因此对于每批我有大约 1000 条消息,每条 100 字节。消息似乎在内部占用了更多 space,因为磁盘上的空闲 space 下降速度比我预期的要快得多。
我正在考虑更改生产者逻辑,它将所有批次放入一条消息中的方式(然后消费者将自行拆分它们)。但我还没有找到任何关于 space 的信息或许多小消息的性能问题,也没有找到任何关于大小和数量之间平衡的准则。而且我对卡夫卡的了解还不足以得出我自己的结论。
谢谢。
producer
将自行 批处理发往同一分区的消息,以避免不必要的调用。
生产者之所以能做到这一点,要归功于它的后台线程。在图像中,您可以看到它如何在将 3 条消息发送到每个分区之前对其进行批处理。
如果你在producer端也设置了compression,它也会压缩(GZip、LZ4、Snappy是有效的编解码器) 在将消息发送到电线之前。这个 属性 也可以在代理端设置(所以生产者发送未压缩的消息,并由代理压缩)。
这取决于您的网络容量来决定您是喜欢较慢的生产者(因为压缩会减慢它)还是更大的网络负载。请注意,为大文件设置较大的压缩级别可能会严重影响您的整体性能。
无论如何,我相信 big/small msg 问题对 consumer
一方的伤害更大;向 Kafka 发送消息既简单又快速(默认行为是异步的,因此 producer
不会太忙)。但在 consumer
方面,您必须查看处理消息的方式:
- 一名消费工人
在这里,您将消费与处理结合起来。这是最简单的方法:消费者设置自己的线程,读取 kafka 消息并处理它。然后继续循环。
- 一个消费者 - 许多工人
在这里你解耦了消费和处理。 在大多数情况下,从 kafka 读取的速度会比处理消息所需的时间更快。 这只是物理学。在这种方法中,一个消费者提供许多分担处理负载的独立工作线程。
有关此 here 的更多信息,就在 Constructors
区域上方。
我为什么要解释这个?好吧,如果你的消息太大,而你选择了第一个选项,你的消费者可能不会在超时间隔内调用 poll()
,所以它会不断地重新平衡。如果您的消息很大(并且需要一些时间来处理),最好选择实施第二个选项,因为消费者将继续自己的方式,调用 poll()
而不会陷入重新平衡。
如果消息太大太多,您可能不得不开始考虑可以将消息缓冲到内存中的不同结构。例如,Pools
、deques
、queues
是完成此操作的不同选项。
您还可以增加轮询超时间隔。这可能会隐藏你死消费者的信息,所以我真的不推荐它。
所以我的回答是:这基本上取决于:您的网络容量、所需的延迟时间和处理能力。如果您能够像处理小消息一样快地处理大消息,那么我就不会在意了。
也许如果您需要过滤和重新处理较旧的消息,我建议您对主题进行分区并发送较小的消息,但这只是一个用例。
有一个微服务,从外面接收一批消息,推送到kafka。每条消息都是单独发送的,因此对于每批我有大约 1000 条消息,每条 100 字节。消息似乎在内部占用了更多 space,因为磁盘上的空闲 space 下降速度比我预期的要快得多。
我正在考虑更改生产者逻辑,它将所有批次放入一条消息中的方式(然后消费者将自行拆分它们)。但我还没有找到任何关于 space 的信息或许多小消息的性能问题,也没有找到任何关于大小和数量之间平衡的准则。而且我对卡夫卡的了解还不足以得出我自己的结论。
谢谢。
producer
将自行 批处理发往同一分区的消息,以避免不必要的调用。
生产者之所以能做到这一点,要归功于它的后台线程。在图像中,您可以看到它如何在将 3 条消息发送到每个分区之前对其进行批处理。
如果你在producer端也设置了compression,它也会压缩(GZip、LZ4、Snappy是有效的编解码器) 在将消息发送到电线之前。这个 属性 也可以在代理端设置(所以生产者发送未压缩的消息,并由代理压缩)。
这取决于您的网络容量来决定您是喜欢较慢的生产者(因为压缩会减慢它)还是更大的网络负载。请注意,为大文件设置较大的压缩级别可能会严重影响您的整体性能。
无论如何,我相信 big/small msg 问题对 consumer
一方的伤害更大;向 Kafka 发送消息既简单又快速(默认行为是异步的,因此 producer
不会太忙)。但在 consumer
方面,您必须查看处理消息的方式:
- 一名消费工人
在这里,您将消费与处理结合起来。这是最简单的方法:消费者设置自己的线程,读取 kafka 消息并处理它。然后继续循环。
- 一个消费者 - 许多工人
在这里你解耦了消费和处理。 在大多数情况下,从 kafka 读取的速度会比处理消息所需的时间更快。 这只是物理学。在这种方法中,一个消费者提供许多分担处理负载的独立工作线程。
有关此 here 的更多信息,就在 Constructors
区域上方。
我为什么要解释这个?好吧,如果你的消息太大,而你选择了第一个选项,你的消费者可能不会在超时间隔内调用 poll()
,所以它会不断地重新平衡。如果您的消息很大(并且需要一些时间来处理),最好选择实施第二个选项,因为消费者将继续自己的方式,调用 poll()
而不会陷入重新平衡。
如果消息太大太多,您可能不得不开始考虑可以将消息缓冲到内存中的不同结构。例如,Pools
、deques
、queues
是完成此操作的不同选项。
您还可以增加轮询超时间隔。这可能会隐藏你死消费者的信息,所以我真的不推荐它。
所以我的回答是:这基本上取决于:您的网络容量、所需的延迟时间和处理能力。如果您能够像处理小消息一样快地处理大消息,那么我就不会在意了。
也许如果您需要过滤和重新处理较旧的消息,我建议您对主题进行分区并发送较小的消息,但这只是一个用例。