web-dev-qa-db-fra.com

Hadoop DistributedCache est obsolète. Quelle est l'API préférée?

Mes tâches de carte nécessitent des données de configuration, que je souhaiterais distribuer via le cache distribué.

Le didacticiel Hadoop MapReduce montre le usage de la classe DistributedCache, à peu près comme suit:

// In the driver
JobConf conf = new JobConf(getConf(), WordCount.class);
...
DistributedCache.addCacheFile(new Path(filename).toUri(), conf); 

// In the mapper
Path[] myCacheFiles = DistributedCache.getLocalCacheFiles(job);
...

Cependant, DistributedCache est marqué comme obsolète dans Hadoop 2.2.0.

Quel est le nouveau moyen privilégié pour y parvenir? Existe-t-il un exemple ou un tutoriel à jour couvrant cette API?

34
DNA

Les API du cache distribué se trouvent dans la classe de travail elle-même. Consultez la documentation ici: http://hadoop.Apache.org/docs/stable2/api/org/Apache/hadoop/mapreduce/Job.html Le code devrait être quelque chose comme 

Job job = new Job();
...
job.addCacheFile(new Path(filename).toUri());

Dans votre code de mappeur: 

Path[] localPaths = context.getLocalCacheFiles();
...
49
user2371156

Pour développer @jtravaglini, la méthode préférée pour utiliser DistributedCache pour YARN/MapReduce 2 est la suivante:

Dans votre pilote, utilisez la Job.addCacheFile()

public int run(String[] args) throws Exception {
    Configuration conf = getConf();

    Job job = Job.getInstance(conf, "MyJob");

    job.setMapperClass(MyMapper.class);

    // ...

    // Mind the # sign after the absolute file location.
    // You will be using the name after the # sign as your
    // file name in your Mapper/Reducer
    job.addCacheFile(new URI("/user/yourname/cache/some_file.json#some"));
    job.addCacheFile(new URI("/user/yourname/cache/other_file.json#other"));

    return job.waitForCompletion(true) ? 0 : 1;
}

Et dans votre mappeur/réducteur, remplacez la méthode setup(Context context):

@Override
protected void setup(
        Mapper<LongWritable, Text, Text, Text>.Context context)
        throws IOException, InterruptedException {
    if (context.getCacheFiles() != null
            && context.getCacheFiles().length > 0) {

        File some_file = new File("./some");
        File other_file = new File("./other");

        // Do things to these two files, like read them
        // or parse as JSON or whatever.
    }
    super.setup(context);
}
20
tolgap

La nouvelle API DistributedCache pour YARN/MR2 se trouve dans la classe org.Apache.hadoop.mapreduce.Job.

   Job.addCacheFile()

Malheureusement, il n’existe pas encore à ce jour de nombreux exemples détaillés de ce type.

http://hadoop.Apache.org/docs/stable/api/org/Apache/hadoop/mapreduce/Job.html#addCacheFile%28Java.net.URI%29

5
jtravaglini

Je n'ai pas utilisé job.addCacheFile (). Au lieu de cela, j'ai utilisé l'option -files telle que "-files /path/to/myfile.txt#myfile" comme auparavant. Ensuite, dans le code du mappeur ou du réducteur, j'utilise la méthode ci-dessous:

/**
 * This method can be used with local execution or HDFS execution. 
 * 
 * @param context
 * @param symLink
 * @param throwExceptionIfNotFound
 * @return
 * @throws IOException
 */
public static File findDistributedFileBySymlink(JobContext context, String symLink, boolean throwExceptionIfNotFound) throws IOException
{
    URI[] uris = context.getCacheFiles();
    if(uris==null||uris.length==0)
    {
        if(throwExceptionIfNotFound)
            throw new RuntimeException("Unable to find file with symlink '"+symLink+"' in distributed cache");
        return null;
    }
    URI symlinkUri = null;
    for(URI uri: uris)
    {
        if(symLink.equals(uri.getFragment()))
        {
            symlinkUri = uri;
            break;
        }
    }   
    if(symlinkUri==null)
    {
        if(throwExceptionIfNotFound)
            throw new RuntimeException("Unable to find file with symlink '"+symLink+"' in distributed cache");
        return null;
    }
    //if we run this locally the file system URI scheme will be "file" otherwise it should be a symlink
    return "file".equalsIgnoreCase(FileSystem.get(context.getConfiguration()).getScheme())?(new File(symlinkUri.getPath())):new File(symLink);

}

Puis dans le mappeur/réducteur:

@Override
protected void setup(Context context) throws IOException, InterruptedException
{
    super.setup(context);

    File file = HadoopUtils.findDistributedFileBySymlink(context,"myfile",true);
    ... do work ...
}

Notez que si j'ai utilisé "-files /path/to/myfile.txt" directement, je dois utiliser "myfile.txt" pour accéder au fichier car il s'agit du nom du lien symbolique par défaut.

2
Jackie Jiang

Aucune des solutions mentionnées ne fonctionnait pour moi de manière complète. C'est possible parce que la version de Hadoop ne cesse de changer, j'utilise hadoop 2.6.4. Essentiellement, DistributedCache est obsolète, je ne voulais donc pas l'utiliser. Comme certains post nous suggèrent d’utiliser addCacheFile (), cela a un peu changé. Voici comment cela a fonctionné pour moi

job.addCacheFile(new URI("hdfs://X.X.X.X:9000/EnglishStop.txt#EnglishStop.txt"));

Ici, X.X.X.X peut être adresse IP principale ou localhost. EnglishStop.txt était stocké dans HDFS à/location. 

hadoop fs -ls /

La sortie est 

-rw-r--r--   3 centos supergroup       1833 2016-03-12 20:24 /EnglishStop.txt
drwxr-xr-x   - centos supergroup          0 2016-03-12 19:46 /test

Drôle mais pratique, # EnglishStop.txt signifie que nous pouvons maintenant y accéder en tant que "EnglishStop.txt" dans le mappeur. Voici le code pour le même

public void setup(Context context) throws IOException, InterruptedException     
{
    File stopwordFile = new File("EnglishStop.txt");
    FileInputStream fis = new FileInputStream(stopwordFile);
    BufferedReader reader = new BufferedReader(new InputStreamReader(fis));

    while ((stopWord = reader.readLine()) != null) {
        // stopWord is a Word read from Cache
    }
}

Cela a juste fonctionné pour moi. Vous pouvez lire la ligne du fichier stocké dans HDFS

1
Somum

J'ai eu le même problème. Et non seulement DistributedCach est déconseillé, mais getLocalCacheFiles et "new Job" également. Donc, ce qui a fonctionné pour moi est le suivant:

Chauffeur:

Configuration conf = getConf();
Job job = Job.getInstance(conf);
...
job.addCacheFile(new Path(filename).toUri());

Dans la configuration Mapper/Reducer:

@Override
protected void setup(Context context) throws IOException, InterruptedException
{
    super.setup(context);

    URI[] files = context.getCacheFiles(); // getCacheFiles returns null

    Path file1path = new Path(files[0])
    ...
}
0
patapouf_ai