مطلب ۸ (قسمت اول) :بررسی MapReduce در مقیاس گسترده با استفاده از هدوپ
در مطالب قبلی چگونگی کار MapReduce با ورودی کم را مشاهده کردید. حالا نوبت آن است که با نگاهی از بالا به پایین سیستم را مورد ارزیابی قرار داده و جریان داده موجود در MapReduce را با ورودی زیاد مورد بررسی قرار دهیم. برای سادگی کار، در مثال قبلی فایل ورودی (Sample.txt) بروی فایل سیستم محلی نگهداری می شد. به منظور گسترش کار، ابتدا می بایست داده ورودی روی یک فایل سیستم توزیع شده که نوعا HDFS (درمطالب بعدی از آن صحبت خواهیم کرد) است، قرار گیرد، تا هدوپ بتواند محاسبات تعریف شده در قالب MapReduce را در سطح کلاستر که در آن هر بخش از داده بروی یک ماشین قرار دارد، به منظور اجرا منتشر نماید.
جریان داده
در آغاز، چند واژه جدید. یک Job در MapRedcue به یک واحد کاری گفته می شود که به دستور client صورت می گیرد که متشکل است از داده ورودی، برنامه MapReduce، تنظیمات اولیه. هدوپ یک Job را به منظور اجرا به تعدادی Task تقسیم می نماید که خود دارای دو نوع است : Map Task , Reduce Task.
به منظور کنترل فرآیند اجرای یک Job دو نوع نود وجود دارد: یک JobTracker و تعدادی JobTracker. TaskTracker تمامی Job های تعریف شده در سیستم را با ایجاد تعدادی Task و اجرای آنها سر زمانبندی مشخصی بروی TaskTracker ها کنترل می نماید. TaskTracker ها Task های تعریف شده را اجرا نموده و در نهایت یک گزارش پیشرفت به JobTracker ارسال می نمایند، که JobTracker هم به ازای هر Job یک رکورد از روند پیشرفت آن بصورت کلی نگهداری می کند. اگر یک Task با شکست مواجه شود، JobTracker می تواند آن Task را بروی یک TaskTracker دیگر مجددا به اجرا درآورد.
هدوپ داده ورودی را به منظور ارسال به یک Job در MapReduce به قطعه های معینی با عنوان Input Splits و یا Splits تقسیم می نماید. هدوپ به ازای هر Split یک Map Task بوجود می آورد، که در آن به ازای هر رکورد از یک Split یک بار تابع Map نوشته شده توسط برنامه نویس فراخوانی می گردد.
داشتن تعداد زیادی Split به این معنی است که مدت زمانی که برای پردازش هر Split صرف می شود در مقایسه با مدت زمان پردازش کل داده ورودی کوچکتر می باشد. بنابراین اگر Split ها به قطعه های کوچکی تقسیم شده و بصورت موازی پردازش شوند، پردازش صورت گرفته متعادل تر خواهد بود به این معنی که یک نود قوی نسبت به یک نود ضعیف برای اجرای یک Job در کلاستر می تواند تعداد Split بیشتری را مورد پردازش قرار دهد. حتی اگر تمامی نود ها از نظر شرایط سخت افزاری یکسان باشند، پردازش هایی که با شکست مواجه می شوند و یا دیگر Job هایی که بصورت همزمان بروی کلاستر در حال اجرا هستند باعث به میان آوردن موضوع تعادل بار در پردازش خواهند شد، و هر قدر Split ها خوب تقسیم بندی شده باشند کیفیت آن افزایش خواهد یافت.
از آنطرف، اگر Split ها خیلی کوچک باشند، سربار مدیریت آنها و همچنین ایجاد Map Task های مربوطه زمان کل اجرای یک Job را تحت تاثیر قرار می دهد. برای بیشتر Job ها، سایز مناسب یک Split معمولا به اندازه یک Block از HDFS می باشد که بصورت پیش فرض 64MB است، گرچه این سایز می تواند در مورد یک کلاستر(برای تمامی فایل های جدید) قابل تغییر باشد و یا در زمان ایجاد یک فایل تعیین شود.
هدوپ نهایت توان خود را به کار می گیرد تا یک Map Task را بروی یک نود جایی که داده ورودی روی HDFS وجود دارد، به اجرا در آورد. که در اصطلاح به آن استفاده بهینه داده موجود در محل (Data Locality Optimization) گفته می شود زیرا در این حالت هدوپ از پهنای باند با ارزش در سطح کلاستر استفاده نمی نماید. (در HDFS به منظور جلوگیری از Data Loss می توان هر Block از داده را روی چند نود کپی نمود) گاهی، اما، تمامی نودهای مربوط به یک Block در HDFS که به عنوان یک Input Split برای یک Map Task می باشد در حال اجرای Map Task های دیگری هستند بنابراین برنامه ریز یک Job بدنبال یک Map Slot خالی روی یک نود در همان Rack به عنوان یکی از همان Block ها می گردد. اکثر اوقات حتی این حالت هم امکانپذیر نمی باشد، بنابراین یک نود خارج از Rack مورد استفاده قرار می گیرد، که در نتیجه باعث انتقال شبکه ای بین Rack ها می شود. این سه حالت در زیر به تصویر کشیده شده است.
Hadoop: The Definitive Guide by Tom White