Hadoop में कई MapReduce जॉब का पीछा करते हुए


124

कई वास्तविक जीवन की स्थितियों में, जहाँ आप MapReduce लागू करते हैं, अंतिम एल्गोरिदम कई MapReduce चरणों को समाप्त करता है।

यानी Map1, Reduce1, Map2, Reduce2, और इसी तरह।

तो आपके पास अंतिम नक्शे से इनपुट के रूप में आवश्यक अंतिम कम से आउटपुट है।

मध्यवर्ती डेटा एक ऐसी चीज़ है जिसे आप (सामान्य रूप से) एक बार पाइपलाइन के सफलतापूर्वक पूरा होने के बाद नहीं रखना चाहते हैं। इसके अलावा, क्योंकि यह मध्यवर्ती डेटा सामान्य रूप से कुछ डेटा संरचना (जैसे 'मानचित्र' या 'सेट') में है, आप इन कुंजी-मान वाले जोड़े को लिखने और पढ़ने में बहुत अधिक प्रयास नहीं करना चाहते हैं।

Hadoop में ऐसा करने का अनुशंसित तरीका क्या है?

क्या एक (सरल) उदाहरण है जो दिखाता है कि इस इंटरमीडिएट डेटा को सही तरीके से कैसे संभालना है, जिसमें बाद में सफाई भी शामिल है?


2
किस मानचित्रण ढांचे का उपयोग कर रहे हैं?
skaffman

1
मैंने प्रश्न को संपादित करने के लिए स्पष्ट किया कि मैं Hadoop के बारे में बात कर रहा हूँ।
नील्स बस्जेस

मैं इसके लिए स्वाइनहार्ड मणि की सलाह दूंगा: github.com/Ganglion/swineherd सर्वश्रेष्ठ, टोबियास
तोबियास

जवाबों:


57

मुझे लगता है कि याहू के डेवलपर नेटवर्क पर यह ट्यूटोरियल आपको इसकी मदद करेगा: चेनिंग जॉब्स

आप का उपयोग JobClient.runJob()। पहली नौकरी से डेटा का आउटपुट पथ आपकी दूसरी नौकरी के लिए इनपुट पथ बन जाता है। इनको पार्स करने के लिए उपयुक्त कोड के साथ आपकी नौकरियों के तर्क के रूप में पारित किया जाना चाहिए और नौकरी के लिए पैरामीटर सेट करना होगा।

मुझे लगता है कि उपरोक्त विधि हालांकि पुराने मैपड एपीआई ने इसे करने का तरीका हो सकता है, लेकिन यह अभी भी काम करना चाहिए। नई मेप्रेडिक्ट एपीआई में एक समान विधि होगी लेकिन मुझे यकीन नहीं है कि यह क्या है।

जहां तक ​​नौकरी खत्म होने के बाद इंटरमीडिएट डेटा निकालने की बात है तो आप अपने कोड में ऐसा कर सकते हैं। जिस तरह से मैंने पहले किया है वह कुछ इस तरह का उपयोग कर रहा है:

FileSystem.delete(Path f, boolean recursive);

जहां पथ डेटा के HDFS पर स्थान है। आपको यह सुनिश्चित करने की आवश्यकता है कि किसी अन्य नौकरी की आवश्यकता होने पर आप केवल इस डेटा को हटा दें।


3
याहू ट्यूटोरियल के लिंक के लिए धन्यवाद। चैनिंग जॉब्स वास्तव में आप क्या चाहते हैं अगर दोनों एक ही रन में हैं। मैं जो देख रहा था वह यह है कि अगर आप उन्हें अलग से चलाने में सक्षम होना चाहते हैं तो आसान तरीका क्या है। उल्लेखित ट्यूटोरियल में मैंने SequenceFileOutputFormat को लिखा "बाइनरी फाइल को बाद की MapReduce नौकरियों में पढ़ने के लिए उपयुक्त" और मैचिंग SequenceFileInputFormat जो इसे करना बहुत आसान बनाते हैं। धन्यवाद।
नील्स बसेजेस

20

ऐसे कई तरीके हैं जिनसे आप इसे कर सकते हैं।

(1) कैस्केडिंग कार्य

पहले काम के लिए JobConf ऑब्जेक्ट "job1" बनाएं और इनपुट डायरेक्ट्री के रूप में "इनपुट" और आउटपुट निर्देशिका के रूप में "अस्थायी" के साथ सभी पैरामीटर सेट करें। इस कार्य को निष्पादित करें:

JobClient.run(job1).

इसके तुरंत बाद, दूसरी नौकरी के लिए JobConf ऑब्जेक्ट "job2" बनाएं और इनपुट टेम्पररी के रूप में "temp" और आउटपुट डायरेक्टरी के रूप में "आउटपुट" के साथ सभी पैरामीटर सेट करें। इस कार्य को निष्पादित करें:

JobClient.run(job2).

(2) दो JobConf ऑब्जेक्ट्स बनाएं और उनमें सभी पैरामीटर सेट करें जैसे (1) सिवाय इसके कि आप JobClient.run का उपयोग न करें।

फिर दो जॉब ऑब्जेक्ट्स को जॉबकॉन्फ़ेट्स पैरामीटर के रूप में बनाएं:

Job job1=new Job(jobconf1); 
Job job2=new Job(jobconf2);

JobControl ऑब्जेक्ट का उपयोग करते हुए, आप नौकरी निर्भरता निर्दिष्ट करते हैं और फिर नौकरी चलाते हैं:

JobControl jbcntrl=new JobControl("jbcntrl");
jbcntrl.addJob(job1);
jbcntrl.addJob(job2);
job2.addDependingJob(job1);
jbcntrl.run();

(३) यदि आपको किसी संरचना की आवश्यकता है जैसे कि Map + | कम करना | मैप *, आप चैनमॅपर और चैनड्रैडर क्लासेस का उपयोग कर सकते हैं जो हाडोप संस्करण 0.19 और उसके बाद आते हैं।


7

वास्तव में ऐसा करने के कई तरीके हैं। मैं दो पर ध्यान केंद्रित करूँगा।

एक राइफल ( http://github.com/cwensel/riffle ) के माध्यम से एक एनोटेशन लाइब्रेरी है जो आश्रित चीजों की पहचान करने और उन्हें निर्भरता (सामयिक) क्रम में 'निष्पादित' करने के लिए है।

या आप कैस्केडिंग में एक कैस्केड (और MapReduceFlow) का उपयोग कर सकते हैं ( http://www.cascading.org/ )। एक भविष्य का संस्करण राइफल एनोटेशन का समर्थन करेगा, लेकिन यह कच्चे एमआर जॉबकोफ नौकरियों के साथ अब बहुत अच्छा काम करता है।

इस पर एक संस्करण हाथ से एमआर नौकरियों का प्रबंधन नहीं करना है, लेकिन कैस्केडिंग एपीआई का उपयोग करके अपने आवेदन को विकसित करना है। तब जॉबकोनफ और जॉब चेनिंग को कैस्केडिंग प्लानर और फ्लो कक्षाओं के माध्यम से आंतरिक रूप से नियंत्रित किया जाता है।

इस तरह से आप अपना समय अपनी समस्या पर ध्यान केंद्रित करने में बिताते हैं, न कि हाडोप नौकरियों के प्रबंधन के यांत्रिकी पर। आप अपने विकास और अनुप्रयोगों को और भी सरल बनाने के लिए अलग-अलग भाषाओं (जैसे क्लोजर या जॉरी) पर भी परत कर सकते हैं। http://www.cascading.org/modules.html


6

मैंने एक के बाद एक JobConf वस्तुओं के साथ काम करते हुए नौकरी की शुरुआत की है। मैंने नौकरियों का पीछा करने के लिए WordCount उदाहरण लिया। एक नौकरी यह बताती है कि दिए गए आउटपुट में एक शब्द को कितनी बार दोहराया गया है। दूसरा काम इनपुट के रूप में पहला काम आउटपुट लेता है और दिए गए इनपुट में कुल शब्दों का पता लगाता है। नीचे कोड है जिसे ड्राइवर वर्ग में रखा जाना चाहिए।

    //First Job - Counts, how many times a word encountered in a given file 
    JobConf job1 = new JobConf(WordCount.class);
    job1.setJobName("WordCount");

    job1.setOutputKeyClass(Text.class);
    job1.setOutputValueClass(IntWritable.class);

    job1.setMapperClass(WordCountMapper.class);
    job1.setCombinerClass(WordCountReducer.class);
    job1.setReducerClass(WordCountReducer.class);

    job1.setInputFormat(TextInputFormat.class);
    job1.setOutputFormat(TextOutputFormat.class);

    //Ensure that a folder with the "input_data" exists on HDFS and contains the input files
    FileInputFormat.setInputPaths(job1, new Path("input_data"));

    //"first_job_output" contains data that how many times a word occurred in the given file
    //This will be the input to the second job. For second job, input data name should be
    //"first_job_output". 
    FileOutputFormat.setOutputPath(job1, new Path("first_job_output"));

    JobClient.runJob(job1);


    //Second Job - Counts total number of words in a given file

    JobConf job2 = new JobConf(TotalWords.class);
    job2.setJobName("TotalWords");

    job2.setOutputKeyClass(Text.class);
    job2.setOutputValueClass(IntWritable.class);

    job2.setMapperClass(TotalWordsMapper.class);
    job2.setCombinerClass(TotalWordsReducer.class);
    job2.setReducerClass(TotalWordsReducer.class);

    job2.setInputFormat(TextInputFormat.class);
    job2.setOutputFormat(TextOutputFormat.class);

    //Path name for this job should match first job's output path name
    FileInputFormat.setInputPaths(job2, new Path("first_job_output"));

    //This will contain the final output. If you want to send this jobs output
    //as input to third job, then third jobs input path name should be "second_job_output"
    //In this way, jobs can be chained, sending output one to other as input and get the
    //final output
    FileOutputFormat.setOutputPath(job2, new Path("second_job_output"));

    JobClient.runJob(job2);

इन नौकरियों को चलाने की कमान है:

बिन / हडोप जार टोटलस्क्रिप्ट।

हमें कमांड के लिए अंतिम नौकरियों का नाम देना होगा। उपरोक्त मामले में, यह कुल एन्क्रिप्शन है।


5

आप कोड में दिए गए तरीके से MR चेन चला सकते हैं।

कृपया ध्यान दें : केवल ड्राइवर कोड प्रदान किया गया है

public class WordCountSorting {
// here the word keys shall be sorted
      //let us write the wordcount logic first

      public static void main(String[] args)throws IOException,InterruptedException,ClassNotFoundException {
            //THE DRIVER CODE FOR MR CHAIN
            Configuration conf1=new Configuration();
            Job j1=Job.getInstance(conf1);
            j1.setJarByClass(WordCountSorting.class);
            j1.setMapperClass(MyMapper.class);
            j1.setReducerClass(MyReducer.class);

            j1.setMapOutputKeyClass(Text.class);
            j1.setMapOutputValueClass(IntWritable.class);
            j1.setOutputKeyClass(LongWritable.class);
            j1.setOutputValueClass(Text.class);
            Path outputPath=new Path("FirstMapper");
            FileInputFormat.addInputPath(j1,new Path(args[0]));
                  FileOutputFormat.setOutputPath(j1,outputPath);
                  outputPath.getFileSystem(conf1).delete(outputPath);
            j1.waitForCompletion(true);
                  Configuration conf2=new Configuration();
                  Job j2=Job.getInstance(conf2);
                  j2.setJarByClass(WordCountSorting.class);
                  j2.setMapperClass(MyMapper2.class);
                  j2.setNumReduceTasks(0);
                  j2.setOutputKeyClass(Text.class);
                  j2.setOutputValueClass(IntWritable.class);
                  Path outputPath1=new Path(args[1]);
                  FileInputFormat.addInputPath(j2, outputPath);
                  FileOutputFormat.setOutputPath(j2, outputPath1);
                  outputPath1.getFileSystem(conf2).delete(outputPath1, true);
                  System.exit(j2.waitForCompletion(true)?0:1);
      }

}

SEQUENCE IS

( JOB1 ) MAP-> REDUCE-> ( JOB2 ) MAP
यह कुंजी सॉर्ट करने के लिए किया गया था
फिर भी एक treemap का उपयोग करने जैसे और भी तरीके हैं फिर भी मैं आपका ध्यान उस तरीके पर केंद्रित करना चाहता हूं जिस तरह से नौकरियां जंजीरों में जकड़ी हुई हैं! !
धन्यवाद




3

हम waitForCompletion(true)नौकरी के बीच निर्भरता को परिभाषित करने के लिए नौकरी की विधि का उपयोग कर सकते हैं ।

मेरे परिदृश्य में मेरे पास 3 नौकरियां थीं जो एक दूसरे पर निर्भर थीं। ड्राइवर वर्ग में मैंने नीचे दिए गए कोड का उपयोग किया है और यह उम्मीद के मुताबिक काम करता है।

public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub

        CCJobExecution ccJobExecution = new CCJobExecution();

        Job distanceTimeFraudJob = ccJobExecution.configureDistanceTimeFraud(new Configuration(),args[0], args[1]);
        Job spendingFraudJob = ccJobExecution.configureSpendingFraud(new Configuration(),args[0], args[1]);
        Job locationFraudJob = ccJobExecution.configureLocationFraud(new Configuration(),args[0], args[1]);

        System.out.println("****************Started Executing distanceTimeFraudJob ================");
        distanceTimeFraudJob.submit();
        if(distanceTimeFraudJob.waitForCompletion(true))
        {
            System.out.println("=================Completed DistanceTimeFraudJob================= ");
            System.out.println("=================Started Executing spendingFraudJob ================");
            spendingFraudJob.submit();
            if(spendingFraudJob.waitForCompletion(true))
            {
                System.out.println("=================Completed spendingFraudJob================= ");
                System.out.println("=================Started locationFraudJob================= ");
                locationFraudJob.submit();
                if(locationFraudJob.waitForCompletion(true))
                {
                    System.out.println("=================Completed locationFraudJob=================");
                }
            }
        }
    }

आपका जवाब निष्पादन के संदर्भ में इन नौकरियों में शामिल होने का तरीका है। मूल प्रश्न सर्वश्रेष्ठ डेटास्ट्रक्चर के बारे में था। तो इस विशिष्ट प्रश्न के लिए आपका उत्तर प्रासंगिक नहीं है।
नील्स बैसज २ 28'१३

2

नया क्लास org.apache.hadoop.mapreduce.lib.chain.ChainMapper इस परिदृश्य की मदद करता है


1
उत्तर अच्छा है - लेकिन आपको कुछ और विवरण जोड़ना चाहिए कि यह क्या करता है या कम से कम एपीआई संदर्भ के लिए एक लिंक है ताकि लोग वोट कर सकें
जेरेमी हजेक

ChainMapper और ChainReducer का उपयोग Reduce से पहले 1 या अधिक mappers और Reduce, कल्पना के बाद 0 या अधिक mappers करने के लिए किया जाता है। (मैपर +) कम करें (मैपर *)। अगर मैं स्पष्ट रूप से गलत हूं तो मुझे सुधारें, लेकिन मुझे नहीं लगता कि यह दृष्टिकोण ओपी के पूछे गए कार्यों को क्रमबद्ध रूप से पूरा करता है।
ऑकोज़ोकिसे

1

यद्यपि जटिल सर्वर आधारित Hadoop वर्कफ़्लो इंजन हैं जैसे, oozie, मेरे पास एक साधारण जावा लाइब्रेरी है जो वर्कफ़्लो के रूप में कई Hadoop नौकरियों के निष्पादन में सक्षम बनाता है। जॉब कॉन्फ़िगरेशन और वर्कफ़्लो को परिभाषित करते हुए इंटर जॉब निर्भरता को JSON फ़ाइल में कॉन्फ़िगर किया गया है। सब कुछ बाहरी रूप से कॉन्फ़िगर करने योग्य है और मौजूदा मानचित्र में किसी भी बदलाव की आवश्यकता नहीं है ताकि वर्कफ़्लो का हिस्सा बनने के लिए कार्यान्वयन कम हो सके।

विवरण यहां पाया जा सकता है। सोर्स कोड और जार जीथब में उपलब्ध है।

http://pkghosh.wordpress.com/2011/05/22/hadoop-orchestration/

प्रणब


1

मुझे लगता है कि oozie परिणामी नौकरियों को पिछली नौकरी से सीधे इनपुट प्राप्त करने में मदद करता है। यह जॉबकंट्रोल के साथ किए गए I / o ऑपरेशन से बचा जाता है।


1

यदि आप अपनी नौकरियों को प्रोग्राम करना चाहते हैं, तो आप जॉबकंट्रोल का उपयोग करना चाहेंगे। उपयोग काफी सरल है:

JobControl jobControl = new JobControl(name);

उसके बाद आप कंट्रोल्डजोब इंस्टेंस जोड़ते हैं। नियंत्रितबॉब निर्भरता के साथ एक नौकरी को परिभाषित करता है, इस प्रकार स्वचालित रूप से इनपुट और आउटपुट प्लगिंग करता है ताकि नौकरियों की "श्रृंखला" फिट हो सके।

    jobControl.add(new ControlledJob(job, Arrays.asList(controlledjob1, controlledjob2));

    jobControl.run();

श्रृंखला शुरू करता है। आप इसे एक स्प्रेड थ्रेड में डालना चाहेंगे। यह आपके चेन की स्थिति की जाँच करने की अनुमति देता है जो इसे चलाता है:

    while (!jobControl.allFinished()) {
        System.out.println("Jobs in waiting state: " + jobControl.getWaitingJobList().size());
        System.out.println("Jobs in ready state: " + jobControl.getReadyJobsList().size());
        System.out.println("Jobs in running state: " + jobControl.getRunningJobList().size());
        List<ControlledJob> successfulJobList = jobControl.getSuccessfulJobList();
        System.out.println("Jobs in success state: " + successfulJobList.size());
        List<ControlledJob> failedJobList = jobControl.getFailedJobList();
        System.out.println("Jobs in failed state: " + failedJobList.size());
    }

0

जैसा कि आपने अपनी आवश्यकता में उल्लेख किया है कि आप MRJob1 का o / p चाहते हैं कि मैं MRJob2 का i / p हूं और इसी तरह, आप इस usecase के लिए oozie वर्कफ़्लो का उपयोग करने पर विचार कर सकते हैं। इसके अलावा आप एचडीएसएफ को अपना मध्यवर्ती डेटा लिखने पर विचार कर सकते हैं क्योंकि यह अगले एमआरजोब द्वारा उपयोग किया जाएगा। और नौकरी पूरी होने के बाद आप अपने मध्यवर्ती डेटा को साफ कर सकते हैं।

<start to="mr-action1"/>
<action name="mr-action1">
   <!-- action for MRJob1-->
   <!-- set output path = /tmp/intermediate/mr1-->
    <ok to="end"/>
    <error to="end"/>
</action>

<action name="mr-action2">
   <!-- action for MRJob2-->
   <!-- set input path = /tmp/intermediate/mr1-->
    <ok to="end"/>
    <error to="end"/>
</action>

<action name="success">
        <!-- action for success-->
    <ok to="end"/>
    <error to="end"/>
</action>

<action name="fail">
        <!-- action for fail-->
    <ok to="end"/>
    <error to="end"/>
</action>

<end name="end"/>

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.