Apache kafka Kafka Connect S3接收器连接器按id字段划分大型主题

Apache kafka Kafka Connect S3接收器连接器按id字段划分大型主题,apache-kafka,apache-kafka-connect,s3-kafka-connector,Apache Kafka,Apache Kafka Connect,S3 Kafka Connector,过去几周,我们一直在致力于将Kafka Connect添加到我们的数据平台,并认为这是一种将Kafka中的数据提取到S3数据湖中的有用方法。我们已经使用了FieldPartitioner和TimeBasePartitioner,并看到了一些相当不错的结果 我们还需要按用户id进行分区-但是尝试过在用户id字段上使用FieldPartitioner后,连接器的速度非常慢-尤其是与按日期等进行分区相比。我知道按id进行分区将创建大量的输出分区,因此不会那么快-这很好,但需要能够保持与制作人沟通 到目

过去几周,我们一直在致力于将Kafka Connect添加到我们的数据平台,并认为这是一种将Kafka中的数据提取到S3数据湖中的有用方法。我们已经使用了FieldPartitioner和TimeBasePartitioner,并看到了一些相当不错的结果

我们还需要按用户id进行分区-但是尝试过在用户id字段上使用FieldPartitioner后,连接器的速度非常慢-尤其是与按日期等进行分区相比。我知道按id进行分区将创建大量的输出分区,因此不会那么快-这很好,但需要能够保持与制作人沟通

到目前为止,我们已经尝试增加内存和堆,但通常不会看到任何内存问题,除非我们将flush.size增加到一个较大的数字。我们还尝试了小尺寸的冲洗,非常小和很大的rotate.schedule.interval.ms配置。我们也研究了网络,但这似乎很好——使用其他分区器,网络保持良好状态


在可能为此浪费大量时间之前,是否有人尝试或成功使用S3接收器连接器按id字段进行分区,尤其是在较大的主题上?或者有人对可能是一个好地方的配置或设置有什么建议吗?

我不习惯卡夫卡的连接器,但我至少会尽力帮助你

我不知道是否可以将连接器配置为kafka主题的分区级别;我想这里有办法做到这一点

一种可能的方法是将注意力集中在客户向卡夫卡经纪人提供产品的步骤上。我的建议是实现您自己的
分区器
,以便“进一步”控制卡夫卡方面的数据发送位置

这是自定义分区器的一个示例/简化。例如,制作人发送的
键具有以下格式:
id\u name\u date
。此自定义分区程序尝试提取第一个元素(
id
),然后选择所需的分区

public class IdPartitioner implements Partitioner 
{       
   @Override
   public int partition(String topic, Object key, byte[] kb, 
                        Object v, byte[] vb, Cluster cl) 
   {
       try 
       {
         String pKey= (String) key;
         int id = Integer.parseInt(pKey.substring(0,pKey.indexOf("_")));
        
          /* getPartitionForId would decide which partition number corresponds
           for the received ID.You could also implement the logic directly here.*/

         return getPartitionForId(id);
       }
       catch (Exception e)
       {return 0;}
   }

   @Override
   public void close() 
   {
     //maybe some work here if needed
   }
}
即使您可能需要在
kafkanconnect
端进行更多的调试,我相信此选项可能会有所帮助。假设您有一个包含5个分区的主题,
getPartitionForId
只检查ID的第一个数字,以确定分区(为简化起见,最小ID为100,最大ID为599)

因此,如果收到的密钥是,f.e:
123_tempdata_20201203
,则分区方法将返回
0
,即第一个分区

public class IdPartitioner implements Partitioner 
{       
   @Override
   public int partition(String topic, Object key, byte[] kb, 
                        Object v, byte[] vb, Cluster cl) 
   {
       try 
       {
         String pKey= (String) key;
         int id = Integer.parseInt(pKey.substring(0,pKey.indexOf("_")));
        
          /* getPartitionForId would decide which partition number corresponds
           for the received ID.You could also implement the logic directly here.*/

         return getPartitionForId(id);
       }
       catch (Exception e)
       {return 0;}
   }

   @Override
   public void close() 
   {
     //maybe some work here if needed
   }
}
(图中显示的是P1而不是P0,因为我相信这个例子看起来更自然,但请注意,第一个分区实际上定义为
分区0
。好吧,老实说,我在绘制此分区时忘记了P0,没有保存模板,所以我不得不寻找借口,比如:看起来更自然)

基本上,这将是在S3上传之前的一次预调整或一次娱乐。

我知道这可能不是理想的答案,因为我不知道您的系统的确切规格我的猜测是,有可能直接将主题分区指向s3位置


如果不可能这样做,至少我希望这能给你一些进一步的想法。干杯

默认的S3分区器使用TopicPartitionsHey@aran!感谢这篇详细的文章,并将此作为一种可能性。你有多少任务和工作人员?我假设问题是每个任务都在处理一个高基数的ID(相比之下,在日期分区窗口中只有几个分区或一个连续增加的日期),并且没有很快达到任何给定ID分区的刷新大小Hey@OneCricketeer,感谢您的评论。对于单个主题,我们有三个分区,我将max.tasks设置为3。在分布式模式下,我们还有3个连接工人。我怀疑刷新大小也是一样的,并尝试将刷新大小设置为1,但仍然看到吞吐量方面的问题。那么,哪一部分实际上很慢?上传文件还是消费?换句话说,您是否在监控消费者滞后?从我所看到的具有真正大的生产者卷和大的刷新大小的连接器来看,连接批处理数据一段时间,然后提交数千个偏移量,但所有数据在S3中似乎都很好;有时候,它只是很慢。我所说的慢,是指消费者似乎从来没有能力跟上生产商的步伐。消费者很难通过主题中当前的数据,随着时间的推移,滞后会慢慢增长。与同一主题相比,使用基于时间的分段器,我们观察到滞后在几个小时内稳步减少。你说有时去那里很慢是什么意思?感谢您的评论!数据上传到S3的速度很慢。但消费者确实在工作。一旦文件被实际上传,偏移量只会被提交(因此延迟只会减少)。这是只向S3交付一次的副产品