任何人都可以解释:
我的用例是,我正在考虑将大量船运数据发送给经纪人,并以ship_id
(如果知道,则为MMSI)作为密钥进行存储。问题是,我不知道那时会收到多少艘船。所以我不能提前定义分区号。
答案 0 :(得分:0)
分区是否可能存储具有多个键的消息?
是的,murmur2哈希(Kafka使用的算法)修改主题中分区的数量可以产生相同的数量。例如,如果您只有一个分区,那么显然任何键都将移至同一分区
键的数量是否超过可用分区的数量?
哈希是取模的,因此它总是被分配一个有效的分区
现在,如果您具有定义明确的密钥,则可以保证将消息按顺序排列到分区中,因此,对分区数量的回答实际上取决于单个分区可以处理的吞吐量,而且没有简短的答案-您要发送多少数据,并且一个消费者可以在“高峰”消耗时从一个分区快速获得该数据?做适当的性能测试,然后将分区号扩大到新主题上,以应对将来可能出现的负载
您还需要考虑“热” /“冷”数据。例如,如果您有10个分区映射到ID的第一位,则所有数据均以偶数开头,则最终将有一半分区为空
答案 1 :(得分:0)
1。 Kafka消息是键和值的形式,并存储在主题中。主题被划分为多个分区程序,每个分区又进一步划分为段,每个段都有一个日志文件,以键-值形式以及消息的索引或偏移量存储实际消息。 密钥是可选的,如果密钥为空,则用于标识要存储消息的分区,然后消息以循环方式存储;而如果密钥不为空,则它将使用具有模块分区大小的哈希密钥,以保证选择其中一个分区。 例如
hash(key)%num_partition
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
List<PartitionInfo> partitions = cluster.partitionsForTopic(topic);
int numPartitions = partitions.size();
if (keyBytes == null) {
int nextValue = nextValue(topic);
List<PartitionInfo> availablePartitions = cluster.availablePartitionsForTopic(topic);
if (availablePartitions.size() > 0) {
int part = Utils.toPositive(nextValue) % availablePartitions.size();
return availablePartitions.get(part).partition();
} else {
// no partitions are available, give a non-available partition
return Utils.toPositive(nextValue) % numPartitions;
}
} else {
// hash the keyBytes to choose a partition
return Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions;
}
}
因此,由于它的使用模块,它将始终将消息存储在可用分区的范围内,这就是为什么多个键可能进入同一分区。消息密钥的主要好处是将相同的消息密钥存储到同一分区。
2。。因此,您不必担心可以根据密钥数定义分区数。如上所述,密钥用于根据默认分区程序逻辑将消息存储到不同的分区。分区号基本上有助于使进程并行化以实现高吞吐量。
注意:您还要确保通过使用键来分区数据可能会导致 分配不均等,因此如果您不用担心,请保持键为null,以选择循环上的分区
其他方法是创建自定义分区程序,以进一步优化分区选择逻辑。 here