Hadoop 自定义分区器:N个不同文件的密钥数

Hadoop 自定义分区器:N个不同文件的密钥数,hadoop,mapreduce,Hadoop,Mapreduce,我的要求是编写一个自定义分区器。我有来自mapper的N个键,例如('jsa','msa','jbac')。长度不是固定的。事实上,它可以是任何词。我的要求是编写一个自定义分区程序,以便它将所有相同的密钥数据收集到同一个文件中。钥匙的数量不是固定的。先谢谢你 谢谢, Sathish.所以映射器输出多个键,每个键需要不同的还原器,每个键都有一个单独的文件 所以第一件事就是编写Partitioner可以实现这一点。默认情况下,hadoop有它自己的内部逻辑,它在键上执行这些逻辑,这取决于它调用red

我的要求是编写一个自定义分区器。我有来自mapper的N个键,例如('jsa','msa','jbac')。长度不是固定的。事实上,它可以是任何词。我的要求是编写一个自定义分区程序,以便它将所有相同的密钥数据收集到同一个文件中。钥匙的数量不是固定的。先谢谢你

谢谢,
Sathish.

所以映射器输出多个键,每个键需要不同的还原器,每个键都有一个单独的文件

所以第一件事就是编写Partitioner可以实现这一点。默认情况下,hadoop有它自己的内部逻辑,它在键上执行这些逻辑,这取决于它调用reducer。因此,如果您想编写一个自定义分区器,那么您必须用自己的逻辑/算法覆盖该默认行为。除非你知道你的钥匙会有多大的变化,否则这个逻辑不会是通用的,你必须根据变化来找出逻辑

我在这里为您提供一个示例,您可以参考它,但它不是通用的

public class CustomPartitioner extends Partitioner<Text, Text>
 {

     @Override
     public int getPartition(Text key, Text value, int numReduceTasks) 
         {

               if(key.toString().contains("Key1"))
               {
                   return 1;
               }else if(key.toString().contains("Key2"))
               {
                   return 2;
               }else if(key.toString().contains("Key3"))
               {
                   return 3;
               }else if(key.toString().contains("Key4"))
               {
                   return 4;
               }else if(key.toString().contains("Key5"))
               { 
                   return 5;
               }else
               {
                   return 7;
               } 
         }
 }
公共类CustomPartitioner扩展了Partitioner
{
@凌驾
public int getPartition(文本键、文本值、int numReduceTasks)
{
if(key.toString()包含(“Key1”))
{
返回1;
}else if(key.toString()包含(“Key2”))
{
返回2;
}else if(key.toString()包含(“Key3”))
{
返回3;
}else if(key.toString()包含(“Key4”))
{
返回4;
}else if(key.toString()包含(“Key5”))
{ 
返回5;
}否则
{
返回7;
} 
}
}
这应该能解决你的问题。只需将键1、键2..等替换为您的键名

如果您不知道密钥名称,您可以参考以下内容编写自己的逻辑:

public class CustomPartitioner<Text, Text> extends Partitioner<K, V> 
{
   public int getPartition(Text key, Text value,int numReduceTasks)
   {
       return (key.toString().charAt(0)) % numReduceTasks;
   }
} 
公共类CustomPartitioner扩展了Partitioner
{
public int getPartition(文本键、文本值、int numReduceTasks)
{
返回(key.toString().charAt(0))%numreductasks;
}
} 
在上面的分区程序中,为了说明如何编写自己的逻辑,我已经演示了,如果去掉键的长度并对减缩器的数量进行%运算,则会得到一个唯一的数字,该数字介于0到减缩器的数量之间,因此默认情况下,会调用不同的减缩器,并在不同的文件中给出输出。但在这种方法中,您必须确保不应为两个键写入相同的值

这是关于定制的分区器

另一个解决方案是,您可以重写MultipleOutputFormat类方法,该类方法将使您能够以通用的方式执行此任务。使用这种方法,您还可以为hdfs中的reducer输出文件生成自定义文件名

注意:确保使用相同的库。不要将mapred与mapreduce库混合使用。org.apache.hadoop.mapred是旧库,org.apache.hadoop.mapreduce是新库


希望这会有所帮助。

我认为最好的方法是:

    public class CustomPartitioner<Text, Text> extends Partitioner<K, V> 
    {
       public int getPartition(Text key, Text value,int numReduceTasks)
       {
           return key.hashCode() % numReduceTasks;
       }
    } 
公共类CustomPartitioner扩展了Partitioner
{
public int getPartition(文本键、文本值、int numReduceTasks)
{
return key.hashCode()%numReduceTasks;
}
} 

所说的“文件”是指“减速机”?如果性能不能保证迫切需要多个减速机,则将密钥传递给单个减速机将产生一个输出文件。您不需要自定义分区器来实现您的目标。这里不清楚您是希望将每个密钥发送到不同的还原器,还是最终希望每个密钥都有一个新文件。您好,GreedyBuddha,是的,我的要求是最终希望每个密钥都有一个新文件。谢谢,但您提到的第一个示例是静态的。我想以动态的方式为每个密钥生成一个文件,因为密钥可以是任何东西。你能给我提个建议吗@user2201536:为此,我提到了“multipleOutpOutFormat类”方法。这是我使用的解决方案,它将帮助您以动态方式为每个密钥生成文件。如果你需要更多的帮助,请告诉我