像Kafka这样的系统如何确保分区内的有序性

7cwmlq89  于 2021-06-07  发布在  Kafka
关注(0)|答案(2)|浏览(400)

我读的这篇文章讨论了Kafka是如何实现的。本文提到,基本上每个shard都是一个只附加的提交日志,这就是它如何保证分区内的排序。
引用文章:
提交日志(也称为预写日志、事务日志)是一种持久有序的数据结构,只支持附加。您不能修改或删除其中的记录。它是从左到右读取,并保证项目排序。

我不明白的是,Kafka如何确保它按照用户想要的顺序附加到日志中。用户先发送对象a,然后再发送对象b,但b先被写入日志,这难道不存在竞争条件吗?
注意:我理解不能保证跨分区排序。这是关于分区内的排序。
旁注:根据另一篇文章,只附加的提交日志是对各种系统的一种抽象,因此这可能会澄清许多其他内容。

os8fio9y

os8fio9y1#

必须指出的是,Kafka保证物品的订购顺序是按照它写的顺序,而不一定是按照预定的顺序。
为了保证您提供密钥的顺序,生产者将在默认分区器算法中使用该密钥,大致如下所示:

hash(key)%numPartitions = partition

这是一个确定性算法,意味着如果密钥不变,分区计数不变,记录将始终写入同一分区,kafka将按接收顺序存储记录。

z9smfwbn

z9smfwbn2#

需要记住的重要一点是,排序保证仅适用于由同一生产者发送的消息。对于由不同生产者发送的消息没有排序保证。在这个场景中,唯一重要的是代理端的接收顺序。如果您想要这样的功能,就必须将它合并到生产者代码本身中。你可以在这个博客里找到更多的细节。
如果您想维持订单,即使生产方出现故障,这可能是相关的:
将retries参数设置为非零,并将max.in.flights.requests.per.session设置为多个,这意味着代理可能无法写入第一批消息,成功写入第二批消息(已在运行中),然后重试第一批消息并成功,从而颠倒顺序。
通常,在可靠的系统中,将重试次数设置为零不是一个选项,因此如果保证顺序至关重要,我们建议在.flight.requests.per.session=1中设置,以确保当一批消息正在重试时,不会发送其他消息(因为这可能会颠倒正确的顺序)。这将严重限制生产商的吞吐量,因此只有在订单很重要时才使用。
发件人:Kafka权威指南
更新-1
所以,我对Kafka制作人的源代码做了一些挖掘。显然,生产者将这些记录添加到一个记录累加器中,然后在批处理已满或经过足够长的时间后,将累加器中所有记录的一部分发送给代理。每个记录都有一个与之相关联的时间戳。我认为代理会按照时间戳的顺序将记录添加到主题中,从而确保在分区中保持顺序。如果有人对Kafka的内在思想有更深入的了解,他也许能够接受或拒绝这个假设。
更新-2
正如cricket在注解中指出的,从累加器中获取的元素的顺序不依赖于时间戳。累加器是一个队列,因此插入和检索顺序是相同的。

相关问题