হাদুপ প্রক্রিয়া রেকর্ডগুলি কীভাবে ব্লকের সীমানা জুড়ে বিভক্ত হয়?


119

অনুযায়ী Hadoop - The Definitive Guide

লজিক্যাল রেকর্ডগুলি যা ফাইলআইনপুট ফর্ম্যাটগুলি সংজ্ঞায়িত করে তা সাধারণত এইচডিএফএস ব্লকগুলিতে ঝরঝরে ফিট করে না। উদাহরণস্বরূপ, একটি টেক্সটইনপুটফর্ম্যাট এর লজিকাল রেকর্ডগুলি লাইন, যা এইচডিএফএসের সীমানা অতিক্রম করবে প্রায়শই বেশি। এটি আপনার প্রোগ্রামের কার্যকারণে কোনও প্রভাব ফেলবে না — লাইনগুলি মিস বা ভাঙা হয়নি, উদাহরণস্বরূপ — তবে এটি সম্পর্কে জানার মতো মূল্য রয়েছে, কারণ এর অর্থ এই যে ডেটা-স্থানীয় মানচিত্র (যা মানচিত্রগুলি একই হোস্টে চলছে তাদের হিসাবে ইনপুট ডেটা) কিছু রিমোট রিড সম্পাদন করবে। এই কারণে সামান্য ওভারহেড সাধারণত তাত্পর্যপূর্ণ নয়।

মনে করুন একটি রেকর্ড রেখা দুটি ব্লক (বি 1 এবং বি 2) জুড়ে বিভক্ত। প্রথম ব্লকের (বি 1) প্রক্রিয়াকরণকারী ম্যাপারটি লক্ষ্য করবে যে শেষ লাইনে কোনও ইওএল বিভাজক নেই এবং পরবর্তী লাইনের ডেটা (বি 2) থেকে বাকী রেখাটি নিয়ে আসে।

দ্বিতীয় ব্লক (বি 2) প্রক্রিয়াকরণকারী কীভাবে নির্ধারণ করে যে প্রথম রেকর্ডটি অসম্পূর্ণ এবং ব্লক (বি 2) এর দ্বিতীয় রেকর্ড থেকে শুরু হওয়া প্রক্রিয়া করা উচিত?

উত্তর:


160

আকর্ষণীয় প্রশ্ন, আমি বিশদটির জন্য কোডটি দেখার জন্য কিছু সময় ব্যয় করেছি এবং এখানে আমার চিন্তাভাবনা রয়েছে। InputFormat.getSplitsবিভাজনগুলি ক্লায়েন্ট দ্বারা পরিচালনা করে , তাই ফাইলআইপুটফর্ম্যাটটি দেখে নীচের তথ্য দেয়:

  • প্রতিটি ইনপুট ফাইল জন্য, ফাইল দৈর্ঘ্য, ব্লক আকার পেতে এবং হিসাবে বিভক্ত আকার নিরূপণ max(minSize, min(maxSize, blockSize))যেখানে maxSizeসাথে সঙ্গতিপূর্ণ mapred.max.split.sizeএবং minSizeহয় mapred.min.split.size
  • FileSplitউপরের গণনা করা বিভক্ত আকারের উপর ভিত্তি করে ফাইলকে বিভিন্ন আকারে ভাগ করুন। এখানে গুরুত্বপূর্ণটি হ'ল প্রতিটিই ইনপুট ফাইলের অফসেটের FileSplitসাথে সম্পর্কিত একটি startপ্যারামিটার দিয়ে শুরু করা হয় । এখনও পয়েন্টটিতে লাইনগুলি পরিচালনা করা হয়নি। কোডটির প্রাসঙ্গিক অংশটি দেখতে এমন দেখাচ্ছে:

    while (((double) bytesRemaining)/splitSize > SPLIT_SLOP) {
      int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);
      splits.add(new FileSplit(path, length-bytesRemaining, splitSize, 
                               blkLocations[blkIndex].getHosts()));
      bytesRemaining -= splitSize;
    }
    

এর পরে, আপনি যদি LineRecordReaderএটি দ্বারা সংজ্ঞায়িত কোনটির দিকে লক্ষ্য করেন TextInputFormat, লাইনগুলি যেখানে পরিচালনা করা হয়:

  • আপনি যখন আরম্ভ করেন LineRecordReaderএটি একটি ইনস্ট্যান্ট করার চেষ্টা করে LineReaderযা লাইনগুলি পড়তে সক্ষম হওয়ার জন্য একটি বিমূর্ততা FSDataInputStream। এখানে দুটি মামলা রয়েছে:
  • যদি কোনও CompressionCodecসংজ্ঞায়িত থাকে, তবে এই কোডেকটি সীমানা পরিচালনা করার জন্য দায়বদ্ধ। সম্ভবত আপনার প্রশ্নের সাথে প্রাসঙ্গিক নয়।
  • যদি কোনও কোডেক না থাকে তবে সেদিকেই আকর্ষণীয় জিনিসগুলি: startআপনার InputSplitযদি এটির চেয়ে 0 টি আলাদা হয় তবে আপনি 1 টি অক্ষর ব্যাকট্র্যাক করে তারপরে the n বা \ r \ n (উইন্ডোজ) দ্বারা চিহ্নিত প্রথম লাইনটি এড়িয়ে যান ! ব্যাকট্র্যাকটি গুরুত্বপূর্ণ কারণ আপনার লাইনের সীমানা বিভক্ত সীমানার সমান হলে, এটি আপনাকে বৈধ লাইনটি এড়িয়ে চলবে না তা নিশ্চিত করে। এখানে প্রাসঙ্গিক কোড:

    if (codec != null) {
       in = new LineReader(codec.createInputStream(fileIn), job);
       end = Long.MAX_VALUE;
    } else {
       if (start != 0) {
         skipFirstLine = true;
         --start;
         fileIn.seek(start);
       }
       in = new LineReader(fileIn, job);
    }
    if (skipFirstLine) {  // skip first line and re-establish "start".
      start += in.readLine(new Text(), 0,
                        (int)Math.min((long)Integer.MAX_VALUE, end - start));
    }
    this.pos = start;
    

সুতরাং যেহেতু বিভাজনগুলি ক্লায়েন্টে গণনা করা হয়, ম্যাপারদের ক্রমানুসারে চালানোর প্রয়োজন হয় না, প্রতিটি ম্যাপার ইতিমধ্যে জানে যে এটি প্রথম লাইনটি ফেলে দেওয়ার প্রয়োজন কিনা।

সুতরাং মূলত যদি আপনার একই ফাইলটিতে প্রতিটি 100Mb এর 2 টি লাইন থাকে এবং সরলকরণের জন্য বলি যে বিভাজনের আকারটি 64Mb। তারপরে যখন ইনপুট বিভাজনগুলি গণনা করা হয়, তখন আমাদের নীচের দৃশ্যপটটি হবে:

  • এই ব্লকে পাথ এবং হোস্টগুলি সমেত 1 বিভক্ত করুন। 200-200 = 0 এমবি, দৈর্ঘ্য 64 এমবিতে শুরু করা হয়েছিল Initial
  • বিভক্ত 2 শুরুতে 200-200 + 64 = 64 এমবি, দৈর্ঘ্য 64 এমবি এ শুরু করা হয়।
  • স্প্লিট 3 200-200 + 128 = 128 এমবি, দৈর্ঘ্য 64 এমবি এ শুরু করা হয়েছে।
  • স্প্লিট 4 শুরুতে 200-200 + 192 = 192Mb, দৈর্ঘ্য 8 এমবিতে শুরু হয়েছিল।
  • ম্যাপার এ বিভাজক 1 টি প্রক্রিয়া করবে, শুরু 0 হবে তাই প্রথম লাইনটি এড়িয়ে চলবে না এবং একটি সম্পূর্ণ লাইন পড়বে যা 64Mb সীমা ছাড়িয়ে যায় তাই দূরবর্তী পাঠ দরকার।
  • ম্যাপার বি বিভাজন 2 বিভক্ত প্রক্রিয়া করবে, শুরু হয়! = 0 সুতরাং 1 লাইন 1 এর শেষের সাথে মিলিত হয়ে 64Mb-1byte এর পরে প্রথম লাইনটি বিভক্ত 2 এ রয়েছে, আমাদের বিভাজনে 2 লাইনের 28Mb আছে রিমোট বাকি 72Mb পড়ুন।
  • ম্যাপার সি বিভাজক 3 প্রক্রিয়া করবে, শুরু হয়! = 0 সুতরাং 128Mb-1byte এর পরে প্রথম লাইনটি এড়িয়ে যান, যা 200Mb এ লাইন 2 এর শেষের সাথে মিলে যায়, যা ফাইলের শেষ তাই কিছুই করবেন না।
  • ম্যাপার ডি ম্যাপার সি এর সমান, এটি 192Mb-1byte এর পরে কোনও নতুন লাইন অনুসন্ধান করে।

এছাড়াও @ প্রবীণস্পৃপতি এটি উল্লেখ করার মতো যে, একটি সীমানা যেখানে \ r এ \ r \ n রিটার্নে থাকবে এমন প্রান্তগুলি ফাংশনটিতে পরিচালিত হয়েছে LineReader.readLine, আমি মনে করি এটি আপনার প্রশ্নের সাথে প্রাসঙ্গিক নয় তবে প্রয়োজনে আরও বিশদ যুক্ত করতে পারে।
চার্লস মেনগুয়ে

ধরে নেওয়া যাক ইনপুটে হুবহু M৪ এমবি সহ দুটি লাইন রয়েছে এবং সুতরাং ইনপুটস্পিটগুলি লাইন সীমানায় ঠিক ঘটে happen সুতরাং, ম্যাপারটি কি সর্বদা দ্বিতীয় ব্লকের লাইনটিকে উপেক্ষা করবে কারণ শুরু! = 0
প্রবীণ শ্রীপতি

6
@ প্রবীণস্পৃপতি সেই ক্ষেত্রে, দ্বিতীয় ম্যাপারটি সূচনাটি দেখবে! = 0, সুতরাং ব্যাকট্র্যাক 1 অক্ষর, যা আপনাকে প্রথম লাইনের the n এর ঠিক আগে ফিরিয়ে আনবে এবং নীচের দিকে to n এড়িয়ে যাবে। সুতরাং এটি প্রথম লাইন এড়িয়ে যাবে তবে দ্বিতীয় লাইনটি প্রত্যাশা অনুযায়ী প্রক্রিয়া করবে।
চার্লস মেনগুয়

@ চার্লসমেঙ্গুই ফাইলের প্রথম লাইনটি কোনওভাবে এড়িয়ে যেতে পারে? কংক্রিটের সাথে, আমার কী = 1 এর সাথে প্রথম লাইন রয়েছে এবং এর মান হয়, তারপরে ফাইলের কোথাও একই কী সহ আরও দুটি লাইন রয়েছে, কী = 1, ভাল = বি এবং কী = 1, ভাল = সি। জিনিসটি হ'ল, আমার রিডুসার {1, [a, b, c] instead এর পরিবর্তে {1, [b, c]} এবং {1, [a] gets পায়} আমি আমার ফাইলটির শুরুতে নতুন লাইন যুক্ত করলে এটি ঘটে না। স্যার কী কারণ হতে পারে?
কোবে-ওয়ান কেনোবি

@ চারলেস মেনগুয়ে যদি এইচডিএফএসের ফাইলটি বাইনারি ফাইল হয় (পাঠ্য ফাইলের বিপরীতে, যার মধ্যে \r\n, \nরেকর্ড কাটাকে উপস্থাপন করা হয়)?
সিউজেড

17

মানচিত্র হ্রাস অ্যালগরিদম ফাইলের শারীরিক ব্লকগুলিতে কাজ করে না। এটি যৌক্তিক ইনপুট বিভাজনে কাজ করে। ইনপুট বিভাজন কোথায় রেকর্ড লেখা ছিল তার উপর নির্ভর করে। একটি রেকর্ড দুটি ম্যাপার বিস্তৃত হতে পারে।

পথ HDFS সেট আপ করা হয়েছে, এটি ডাউন বৃহৎ ব্লক মধ্যে খুব বড় ফাইল (উদাহরণস্বরূপ, 128MB পরিমাপ) ভঙ্গ, এবং দোকান ক্লাস্টার বিভিন্ন নোড এই ব্লক তিন কপি।

এইচডিএফএসের এই ফাইলগুলির বিষয়বস্তু সম্পর্কে কোনও সচেতনতা নেই। একটি রেকর্ড ব্লক-এ শুরু করা হতে পারে তবে সেই রেকর্ডের শেষে ব্লক-বিতে উপস্থিত থাকতে পারে ।

এই সমস্যা সমাধানের জন্য, হ্যাডোপ ফাইল ব্লকগুলিতে সঞ্চিত ডেটার যৌক্তিক উপস্থাপনা ব্যবহার করে, যা ইনপুট বিভক্ত হিসাবে পরিচিত। যখন কোনও মানচিত্রে চাকরির ক্লায়েন্ট ইনপুটটি বিভক্ত করে গণনা করে , এটি নির্ধারণ করে যে কোনও ব্লকের প্রথম পুরো রেকর্ডটি কোথায় শুরু হয় এবং যেখানে ব্লকের সর্বশেষ রেকর্ডটি শেষ হয়

মূল বিষয়:

যে কোনও ক্ষেত্রে যখন কোনও ব্লকের সর্বশেষ রেকর্ড অসম্পূর্ণ থাকে, ইনপুট বিভাজনে পরবর্তী ব্লকের জন্য অবস্থানের তথ্য এবং রেকর্ডটি সম্পূর্ণ করার জন্য প্রয়োজনীয় ডেটার বাইট অফসেট অন্তর্ভুক্ত থাকে।

নীচের চিত্রটি দেখুন।

এখানে চিত্র বর্ণনা লিখুন

এই নিবন্ধটি এবং এসই সম্পর্কিত সম্পর্কিত প্রশ্নটি দেখুন: হ্যাডোপ / এইচডিএফএস ফাইল বিভাজন সম্পর্কে

আরও বিবরণ ডকুমেন্টেশন থেকে পড়া যেতে পারে

মানচিত্র-হ্রাস কাঠামো এতে কাজের ইনপুট ফর্ম্যাটটির উপর নির্ভর করে:

  1. কাজের ইনপুট-নির্দিষ্টকরণের বৈধতা দিন ate
  2. লজিকাল ইনপুটস্প্লিটগুলিতে ইনপুট ফাইল (গুলি) স্প্লিট-আপ করুন, যার প্রত্যেকটি তারপরে স্বতন্ত্র ম্যাপারে নির্ধারিত হয়।
  3. প্রতিটি ইনপুটস্প্লিট প্রক্রিয়াজাতকরণের জন্য পৃথক ম্যাপারের কাছে নিযুক্ত করা হয়। বিভক্ত টুপল হতে পারেInputSplit[] getSplits(JobConf job,int numSplits) এই জিনিসগুলির যত্ন নেওয়ার জন্য এপিআই।

ফাইলআইপুটফর্ম্যাট , যা InputFormatপ্রয়োগ করা getSplits() পদ্ধতিটি প্রসারিত করে । গ্রেপকোডে এই পদ্ধতির ইন্টার্নালগুলি দেখুন


7

আমি এটি নিম্নলিখিত হিসাবে দেখছি: ইনপুট ফর্ম্যাট ডেটার প্রকৃতি বিবেচনায় নিয়ে লজিক্যাল স্প্লিটগুলিতে ডেটা বিভক্ত করার জন্য দায়বদ্ধ।
কিছুই এটি করতে বাধা দেয় না, যদিও এটি চাকরিতে উল্লেখযোগ্য প্রচ্ছন্নতা যুক্ত করতে পারে - সমস্ত যুক্তি এবং পড়া কাঙ্ক্ষিত বিভক্ত আকারের সীমানার চারপাশে জব ট্র্যাকারে ঘটবে।
সবচেয়ে সহজ রেকর্ড সচেতন ইনপুট ফর্ম্যাটটি টেক্সটইনপুট ফর্ম্যাট। এটি নিম্নলিখিত হিসাবে কাজ করছে (যতদূর আমি কোড থেকে বুঝতে পেরেছি) - ইনপুট ফর্ম্যাটটি আকার অনুসারে বিভাজন তৈরি করে, লাইন নির্বিশেষে, তবে লাইনরেকর্ডারিডার সর্বদা:
ক) বিভাজনে প্রথম লাইনটি এড়িয়ে যায় (বা এর অংশ) যদি তা না হয় প্রথম বিভাজন
খ) শেষের দিকে বিভাজনের সীমানার পরে একটি লাইন পড়ুন (যদি ডেটা এটি উপলব্ধ থাকে, তবে এটি শেষ বিভাজন নয়)।


Skip first line in the split (or part of it), if it is not the first split- অ-প্রথম ব্লকে যদি প্রথম রেকর্ডটি সম্পূর্ণ হয় তবে এই যুক্তিটি কীভাবে কাজ করবে তা নিশ্চিত হন না।
প্রবীণ শ্রীপতি

যতদূর আমি কোডটি দেখতে পাচ্ছি - প্রতিটি বিভাজনে এটি + পরবর্তী লাইনে কী আছে তা পড়ে। সুতরাং যদি লাইন ব্রেকটি ব্লকের সীমানায় না থাকে - এটি ঠিক আছে। লাইন ব্রেক যখন অবরুদ্ধ ব্লকের
সীমানায়

3

যা আমি বুঝতে পেরেছি, যখন FileSplitপ্রথম ব্লকের জন্য আরম্ভ করা হয়, তখন ডিফল্ট কনস্ট্রাক্টর বলা হয়। সুতরাং শুরু এবং দৈর্ঘ্যের মানগুলি শূন্য হয়। মুষ্টি ব্লকের প্রসেসিংয়ের শেষে, যদি শেষ লাইনটি অসম্পূর্ণ হয়, তবে দৈর্ঘ্যের মান বিভাজনের দৈর্ঘ্যের চেয়ে বেশি হবে এবং এটি পরবর্তী ব্লকের প্রথম লাইনটিও পড়বে। এ কারণে প্রথম ব্লকের জন্য শুরুর মান শূন্যের চেয়ে বেশি হবে এবং এই শর্তের অধীনে, LineRecordReaderদ্বিতীয় ব্লকের প্রথম মুদ্রা রেখাটি এড়িয়ে যাবে। ( উত্স দেখুন )

যদি প্রথম ব্লকের শেষ লাইনটি সম্পূর্ণ হয় তবে দৈর্ঘ্যের মান প্রথম ব্লকের দৈর্ঘ্যের সমান এবং দ্বিতীয় ব্লকের জন্য শুরুর মান শূন্য হবে। যে ক্ষেত্রে LineRecordReaderপ্রথম লাইন এড়িয়ে যান এবং দ্বিতীয় ব্লক ফর্ম শুরুতে পড়া করা হবে না।

বোধ হয়?


2
এই পরিস্থিতিতে, ম্যাপারগুলিকে একে অপরের সাথে যোগাযোগ করতে হবে এবং নির্দিষ্ট ব্লকের শেষ লাইনটি সম্পূর্ণ না হলে ক্রমগুলি ব্লকগুলি প্রক্রিয়াজাত করতে হয়। নিশ্চিত না যে এটি এভাবে কাজ করে।
প্রবীণ শ্রীপতি

1

নির্মাণকারীর লাইনরেকর্ডারিডার.জভা এর হ্যাডোপ উত্স কোড থেকে: আমি কিছু মন্তব্য পেয়েছি:

// If this is not the first split, we always throw away first record
// because we always (except the last split) read one extra line in
// next() method.
if (start != 0) {
  start += in.readLine(new Text(), 0, maxBytesToConsume(start));
}
this.pos = start;

এ থেকে আমি বিশ্বাস করি যে হ্যাডুপ প্রতিটি বিভাজনের জন্য একটি অতিরিক্ত লাইন পড়বে (বর্তমান বিভাজনের শেষে, পরবর্তী বিভাজনে পরবর্তী লাইনটি পড়বে) এবং যদি প্রথম বিভাজন না হয় তবে প্রথম লাইনটি ফেলে দেওয়া হবে। যাতে কোনও লাইন রেকর্ড হারিয়ে না যায় এবং অসম্পূর্ণ থাকে


0

ম্যাপারদের যোগাযোগ করতে হবে না। ফাইল ব্লকগুলি এইচডিএফএসে রয়েছে এবং বর্তমান ম্যাপারটি (রেকর্ডারিডার) লাইনের বাকী অংশের ব্লকটি পড়তে পারে। পর্দার আড়ালে এটি ঘটে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.