2013-02-20 6 views
5

Gibt es eine Möglichkeit, ein benutzerdefiniertes Konfigurationsobjekt in Hadoop während Map/Reduce festzulegen und (später) zu erhalten?Ausgeben von benutzerdefinierten Konfigurationswerten in Hadoop

Nehmen Sie zum Beispiel eine Anwendung an, die eine große Datei vorverarbeitet und dynamisch bestimmte Eigenschaften der Datei ermittelt. Weiterhin wird angenommen, dass diese Eigenschaften in einem kundenspezifischen Java-Objekt (z. B. einem Properties-Objekt, aber nicht ausschließlich, da einige keine Zeichenfolgen sind) gespeichert werden und anschließend für jede der Karten und der Reduzierungsaufträge notwendig sind.

Wie kann die Anwendung diese Konfiguration "propagieren", so dass jede Mapper- und Reducer-Funktion bei Bedarf darauf zugreifen kann?

Ein Ansatz könnte die set(String, String) Methode der JobConf Klasse und zum Beispiel zu verwenden sein, das Konfigurationsobjekt wie ein über den zweiten Parameter JSON String serialisiert, aber dies kann zu viel sein wie ein Hack und dann die entsprechenden JobConf Auf die Instanz muss auf jeden Fall zugegriffen werden (und Reducer) (z. B. nach einem Ansatz wie dem in einer earlier question vorgeschlagenen).

Antwort

8

Es sei denn, ich etwas fehle, wenn Sie jede Eigenschaft, die Sie brauchen in Ihrem M/R Job enthält, ein Properties Objekt haben müssen Sie einfach den Inhalt des Properties Objekt an die Hadoop Configuration Objekt schreiben. Zum Beispiel so etwas wie diese:

Configuration conf = new Configuration(); 
Properties params = getParameters(); // do whatever you need here to create your object 
for (Entry<Object, Object> entry : params.entrySet()) { 
    String propName = (String)entry.getKey(); 
    String propValue = (String)entry.getValue(); 
    conf.set(propName, propValue); 
} 

Dann in Ihrer M/R Job, können Sie das Context Objekt verwenden Ihre Configuration sowohl in der Mapper zurück zu bekommen (die map-Funktion) oder die Reduzierung (die reduce-Funktion) dies, wie:

public void map(MD5Hash key, OverlapDataWritable value, Context context) 
    Configuration conf = context.getConfiguration(); 
    String someProperty = conf.get("something"); 
    .... 
} 

Beachten Sie, dass, wenn das Configuration Objekt verwenden, können Sie auch die Context in den setup und cleanup Methoden zugreifen können, nützlich sein, eine Initialisierung zu tun, wenn nötig.

Auch ist es wert, könnten Sie wahrscheinlich direkt rufen Sie die addResource Methode aus dem Configuration Objekt unter Angabe Ihrer Eigenschaften direkt als InputStream oder einer Datei hinzufügen, aber ich glaube, das ist eine XML-Konfiguration wie die regelmäßigen Hadoop XML configs sein muss, so das könnte einfach übertrieben sein.

EDIT: Bei Nicht-String-Objekte, würde ich die Serialisierung mit raten: Sie können Ihre Objekte serialisiert werden, und wandeln sie dann in Strings (wahrscheinlich sie mit Base64 zum Beispiel codieren, wie ich bin nicht sicher, was würde passieren, wenn Sie ungewöhnliche Zeichen haben), und dann auf der Mapper/Reducer-Seite deserialisieren Sie die Objekte von den Strings, die Sie von den Eigenschaften innerhalb Configuration erhalten.

Ein anderer Ansatz wäre, die gleiche Serialisierungstechnik zu verwenden, aber stattdessen in HDFS zu schreiben und diese Dateien dann zu DistributedCache hinzuzufügen. Klingt etwas übertrieben, aber das würde wahrscheinlich funktionieren.

+0

Dies ist in Ordnung, wenn alle Eigenschaften Strings sind. In meinem Anwendungsfall sind es einige nicht, sie sind (ziemlich komplexe) benutzerdefinierte Java-Objekte, die sowohl für die Karte als auch für die reduzierten Teile benötigt werden. Aber +1 für die Antwort sowieso. :-) – PNS

+1

@PNS Nun, wenn Sie Nicht-String-Objekt übergeben möchten, könnten Sie immer Ihre Objekte serialisieren, bevor Sie die zu Strings konvertieren und diese Strings an die 'Konfiguration' übergeben, und dann im Mapper/Reducer de-serialisieren Objekte. Ich glaube nicht, dass es einen nativen Weg gibt, Objekte auf diese Art zu übergeben.Sie könnten das Objekt wahrscheinlich auch in eine Datei serialisieren und in HDFS ablegen und dann diese Datei wahrscheinlich mit dem 'DistributedCache' erhalten. –

+0

Ja, Serialisierung scheint trotzdem notwendig zu sein, da MapReduce eine verteilte Anwendung ist. – PNS