【问题标题】:Kafka Deletes segments even before segment size is reachedKafka 甚至在达到段大小之前就删除段
【发布时间】:2019-06-27 14:23:50
【问题描述】:

我在本地机器上玩Kafka,我添加了以下Topic配置:

bin/kafka-topics.sh --zookeeper localhost:2181 --alter --topic topic1 config retention.ms=60000
bin/kafka-topics.sh --zookeeper localhost:2181 --alter --topic topic1 —config file.delete.delay.ms=40000
bin/kafka-topics.sh --zookeeper localhost:2181 --alter --topic topic1 --config segment.bytes=400000

我的理解是,当分段达到上面定义的分段大小(segment.bytes=400000)加上分段中的每条消息都比上面定义的保留时间更早(retention.ms=60000)时,分段将被删除.

我注意到只有 35 个字节的段,其中仅包含一条消息,在一分钟后被删除(可能更多)

我从哪里得到这些信息?来自Linkedin工程师关于删除过程如何工作的帖子:

留存率将基于两种留存率的组合 和段大小设置(作为旁注,建议使用 log.retention.ms 和 log.segment.ms,而不是小时配置。那是 出于遗留原因,但 ms 配置更加一致)。作为 消息被 Kafka 接收,它们被写入当前打开的 每个分区的日志段。该段旋转时 已达到 log.segment.bytes 或 log.segment.ms 限制。一次 发生这种情况时,日志段被关闭并打开一个新的。仅有的 日志段关闭后是否可以通过保留删除 设置。一旦日志段关闭并且所有消息 段中的旧于 log.retention.ms 或总分区 size 大于 log.retention.bytes,则日志段为 清除。

链接:How the retention works

【问题讨论】:

    标签: apache-kafka


    【解决方案1】:

    有一个代理配置 - log.retention.check.interval.ms 会影响此测试。默认为 5 分钟。因此,每 5 分钟检查一次代理日志段,以查看是否可以根据保留策略删除它们。

    topic1 配置设置了保留策略 (retention.ms=60000),因此如果 topic1 的活动段中至少有一条现有消息,则该段将被关闭并删除闲置足够长的时间。由于 log.retention.check.interval.ms 是代理配置,因此不受主题更改的影响。在最后一条消息生成到段之后,retention.ms 也必须传递。因此,在向该段生成最后一条消息后,段将在不少于retention.ms 毫秒且不超过retention.ms+log.retention.check.interval.ms 内被删除。

    因此,“仅包含一条消息的仅 35 字节的段,在一分钟后被删除(可能更多一点)”发生了,因为保留检查几乎是在消息生成到该段后立即发生的。然后,Broker 只需等待 60 秒以确保不会向该段生成新消息(在这种情况下不会发生删除),并且由于没有消息,因此它删除了该段

    其他 topic1 配置在这里没有发挥太大作用。

    file.delete.delay.ms=40000 刚刚定义了在代理已经决定删除​​该段之后,它应该等待 40 秒来执行此操作

    segment.bytes=400000 在此测试中没有任何影响。它定义了在将 400000 字节存储到段之后,应该关闭它并推出新的。

    【讨论】:

      【解决方案2】:

      你错过了解释你引用的一些陈述:

      当达到 log.segment.bytes 或 log.segment.ms 限制时,将轮换该段。

      这清楚地表明旋转可以由大小或时间触发。这是,而不是

      一旦发生这种情况,日志段就会关闭。 [...] 一旦日志段关闭并且该段中的所有消息都早于 log.retention.ms 或总分区大小大于 log.retention.bytes,那么日志段将被清除。

      这样,当一个段被时间触发旋转关闭后,不管它的大小,它都可以被删除。

      【讨论】:

      • 等等,我不太确定我是否会错过解释这些陈述。让我们分解一下:在我的情况下,当达到 segment.bytes(segment.bytes=400000)时,该段将被旋转。 THEN,如果轮换段中的所有消息都早于retention.ms = 60000,则删除该段。
      • 其实我只是检查了segment.ms相关的值。它设置为 604800000(168 小时)。因此,我们甚至可以丢弃 segment.ms 设置为非常低的值(并且丢弃段正在旋转,因为在 segment.bytes 属性之前达到了 segment.ms 属性)。
      • 段未满但保留时间已过时也可以轮换。因此这是不正确的:“在我的情况下,当达到segment.bytes(segment.bytes = 400000)时,该段将被旋转”。在您的情况下,由于保留时间过去,该段会被轮换。此外,保留时间与“segment.ms”无关——“segment.ms”实际上是除段大小和保留时间之外的第三个轮换策略/触发器。
      • 我觉得你和我都一样,但也许我解释得不是很好。让我们看看retention.ms 定义:“如果我们使用删除保留策略,此配置控制在我们丢弃旧日志段以释放空间之前保留日志的最长时间。”所以retention.ms是丢弃旧段的保留期。我知道retention.ms 和segment.ms 不相关。我没有混合两者。
      • 我同意这个说法。但是,如果您的当前段尚未满,并且保留时间已过,则该段将被关闭并变成“旧日志段”,即使它未满。因此,它将被删除。也许文档不够清楚——但你观察到这种行为——那么为什么你认为我的解释不正确?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-21
      • 2023-03-14
      • 2020-10-29
      • 1970-01-01
      • 1970-01-01
      • 2018-03-03
      • 2020-03-01
      相关资源
      最近更新 更多