写点什么

面试官:Kafka 中的 key 有什么用?

作者:王磊
  • 2024-08-28
    陕西
  • 本文字数:1208 字

    阅读完需:约 4 分钟

面试官:Kafka中的key有什么用?

我们在使用 Kafka 时,最简单、最常用的方式是只设置 topic(主题)和 value(消息体),如下所示:



这样的话获取消息的代码也很简单,如下所示:


@KafkaListener(topics = "mytopic", groupId = "my-group")public void listen(String data) {    System.out.println("监听到消息:" + data);}
复制代码


但是,除了我们可以设置和传递 topic 和 value 之外,我们还可以传递 key,如下图所示:



那问题来了,发送消息时设置这个 key 有什么用呢?

key 的作用

发送消息时,设置 key 的作用如下:


1.决定分区

当生产者发送消息时,如果指定了 key,Kafka 会根据 key 的 hash 值来决定这条消息应该发送到哪个分区。


如果没有指定 key,Kafka 会采用轮询(早期版本)或随机(最新版本)的方式将消息分配到其他分区中。


分区的具体实现源码在 DefaultPartitioner 中 partition 方法中体现,核心源码如下:


public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster, int numPartitions) {    return keyBytes == null ? this.stickyPartitionCache.partition(topic, cluster) : BuiltInPartitioner.partitionForKey(keyBytes, numPartitions);}
复制代码


指定 key 之后的分区实现代码如下:


public static int partitionForKey(byte[] serializedKey, int numPartitions) {    return Utils.toPositive(Utils.murmur2(serializedKey)) % numPartitions;}
复制代码


以上源码的大概含义是:使用 MurmurHash2 算法对字节数组 serializedKey 进行哈希运算,并将其结果转换为正数,然后对 numPartitions 取模,以确定键在分区中的位置,返回值表示键所在的分区编号。


所以,从上述源码可以看出,发送消息如果设置了 key 之后,会将相同 key 放到同一个分区中。

2.保证消息顺序

在 Kafka 中,同一个分区中的消息是有序的。而相同的 key,根据上面的分区算法可知,它们会存放到同一个分区,这样就能保证消息的有序性了。

3.消息过滤

对于某些应用场景,消费者可以根据消息的键来进行过滤或聚合操作。例如,在实时数据分析场景中,可能需要对具有相同键的消息进行分组处理。


Kafka 设置了 key 之后,可以通过以下方式实现消息过滤,如下代码所示:


@KafkaListener(topics = "topicName", groupId = "groupId")public void listen(String message, ConsumerRecord<?,?> record) {    Object key = record.key();    if (key instanceof String && ((String) key).matches("regexPattern")) {        // 处理满足正则表达式条件的消息    }}
复制代码


也就是,我们在接收到消息之后,通过对 key 的正则匹配实现消息的过滤和聚合等操作。

课后思考

保证 Kafka 消息的有序性,除了设置 key 之外,还有哪些实现手段?


本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

用户头像

王磊

关注

javacn.site 2018-08-25 加入

我的小站:javacn.site

评论

发布
暂无评论
面试官:Kafka中的key有什么用?_王磊_InfoQ写作社区