对粗略排序的流进行排序的最佳方法是什么?

时间:2021-02-19 08:24:43

标签: algorithm sorting apache-kafka

我有一个 kafka 主题 unsorted,其键是时间戳。时间戳是大致排序的,我希望它们近乎实时地完全排序。目前我使用堆来缓冲多达 10,000 条消息,并将一半的有序消息发送到主题 sorted。有没有更好的方法来做到这一点?

'大致有序'意味着消息是用当前时间(这是关键)产生的,但网络延迟(+-1秒)使消息到达时略微无序。两条消息的最大时间差为 2 秒。每秒产生大约 5k 条消息。

3 个答案:

答案 0 :(得分:1)

我会创建一个足够大的缓存(数组)来容纳我们在 2 秒内期望的最大包数(因为必须处理 +/- 1 秒的延迟) 对于到达的包裹执行插入 ( O(log n) )

并删除旧消息(比最新消息早 2 秒以上)并将它们发送到输出。


可选的额外优化:
为了避免在从缓存中删除“旧”消息时进行复制,您可以将数组组织为 zyclic-array(如环形缓冲区)

答案 1 :(得分:0)

我最近自己实现了类似的东西。

我有两种机制:

  1. 基于时间:
  • 保留上次发送消息的“lastFlush”时间戳。
  • 向内部缓冲区添加新消息
  • 每次轮询后,如果 lastFlush 时间戳大于 2s,则按顺序发送所有大于 2s 的消息,并更新 lastFlush 时间戳。
  1. 基于缓冲区大小:
  • 每次轮询后,如果缓冲区已满,则发送缓冲区中最旧的一半,无论其年龄如何。

第二种机制仍然可能会导致乱序消息是缓冲区不够大,所以应该是例外。

顺便说一句,我们以 100 毫秒的超时时间进行了消费者轮询,以确保我们继续刷新缓冲区,即使没有新消息到达也是如此。

将缓冲区保留在内存中的另一个问题是如何确保在处理器出现故障时不会丢失消息。

我们使用手动提交解决了这个问题,只在刷新后提交传入的消息。这确保了当一个消费者被杀死时,缓冲区中的消息会自动在接管分区的消费者上重播。但是管理起来非常复杂,因为当消息乱序时,我们有时不得不保留旧的偏移量,而新的消息已经被刷新。我们必须跟踪每个 kafka 分区的不同偏移量。

答案 2 :(得分:0)

如果我假设您的时间戳只有 1/1000 秒准确,那么在 2 秒间隔内只有 2000 个不同的时间戳。

因此,您可以简单地创建 2000 个引用每个时间戳的消息列表。

插入将是O(1)(附加到相应的列表)

不要忘记将旧条目写入您的输出。为避免混淆,只需为每个列表存储一个时间戳,以检测它是否超过 2 秒并需要写入输出。


如果您的时间戳更准确,您可以选择更多列表或对列表进行内部排序以获得更高的精度

相关问题