بررسی فایل سیستم HDFS از Apache Hadoop و امکان سنجی استفاده از آن به عنوان یک ذخیره ساز برودکست – بخش دوم

در بخش قبلی ما ساختار فایل سیستم HDFS و نحوه پیاده سازی High availability در آن را بررسی کرده و به نحوه دسترسی به فایل های داخل آن پرداختیم. در این بخش ما به ما عملیات درونی read / write را بررسی می کنیم و به روش چیده شدن بلوک ها داخل کلاستر می پردازیم. علاوه بر این در این بخش ما بعضی ابزارهای hdfs را بررسی کرده و در مورد اینکه hdfs آیا به عنوان یک ذخیره ساز برودکست قابل استفاده است یا نه تصمیم می گیریم.

شکافتن داخل یک عملیات read

در یک عملیات read در HDFS ، کلاینت ابتدا با NameNode تماس گرفته و متادیتای فایل مورد نظر و آدرس نودهایی که بلوک های اطلاعات در آن ذخیره شده اند می گیرد. سپس کلاینت با دیتانود ها تماس گرفته و به ترتیب بلوک های فایل را از آنها می خواند. در مورد خواندن باید به موارد زیر توجه داشت:
عملیات خواندن بصورت عادی بصورت ترتیبی است. یعنی هر بلوک داده از یک نود خوانده شده و بعد از کامل شدن آن کلاینت به سراغ نود بعدی میرود. به عبارت دیگر با اینکه hdfs بصورت بالقوه امکان خواندن بلوک های مختلف از چندین نود بصورت پارالل برای افزایش سرعت را دارد، اما بصورت پیش فرض از آن استفاده نمی کند. برای استفاده از حالت کپی پارالل باید از distcp استفاده کرد که بعدا در مورد آن توضیح خواهیم داد.

اگر خواندن یک بلوک از یک DataNode ناموفق باشد، کلاینت آن نود را برای خودش علامت میزند تا مجدد سراغ آن برای بلوک های بعدی نرود، در ضمن NameNode را از وجود دیتانود خراب مطلع می کند و سپس به سراغ نزدیکترین نود دیگری که replica این بلوک را دارد می رود تا کپی بلوک را از آن بخواند. علاوه بر این بعد از اینکه یک بلوک دیتا خوانده شد، چک سام آن با محتویات آن چک می شود تا محتوای بلوک خراب نباشد و اگر خراب باشد به NameNode اطلاع داده می شود تا ترتیب کپی بلوک از روی یک نود سالم را بدهد و خود بلوک هم از یک نود سالم دیگر مجدد خوانده می شود.
عملیات خواندن بلوک ها همواره از روی نودی که نزدیکتری نود به کلاینت است انجام می شود. توجه داشته باشید که دراینجا نزدیک بودن به معنی پهنای باند شبکه بیشتر بین دو نود است. اما از آنجا که امکان اندازی گیری پهنای باند بین دو نود به این راحتی وجود ندارد، از قانون زیر برای تشخیص نزدیک بودن دو نود به هم استفاده می شود.

  • الف: دو پروسس روی یک نود نزدیکترین فاصله را به هم دارند.
  • ب: دو نود روی یک راک از دو نود روی دو راک مختلف به هم نزدیکتر هستند.
  • ج: نودهای روی دو راک مختلف در یک دیتاسنتر، از نودهای داخل دو دیتاسنتر مختلف به هم نزدیکتر هستند.

همانطوری که دیده می شود این معادل نزدیکی فیزیکی نودها به هم است، اما از آنجا که در واقعیت هم دو نود داخل یک راک به یک سوییچ (و از طریق پهنای باند داخلی سوییچ) با هم ارتباط دارند و نودهای داخل راک های مختلف به سوییچ های مختلف با آپ لینک به هم وصل میشوند و پهنای باند کمتری دارند، این قانون در واقعیت هم صادق است.

شکافتن داخل یک عملیات write

در یک عملیات write کلاینت ابتدا به NameNode اطلاع می دهد که قصد دارد که فایل را روی کلاستر بنویسد و از NN آدرس دیتا نود هایی که باید بلوک های دیتا روی آن نوشته شود میگیرد. سپس کلاینت دیتا را بلوک های مختلف تقسیم کرده (split) و آنها را در یک صف که data que خوانده می شود و توسط Data Streamer مصرف میشود می چیند. دیتا استریمر به ترتیب بلوک های دیتا را برداشته و آنها را روی دیتا نود تخصیص داده شوده می نویسد. توجه داشته باشید که در اینجا کلاینت هر بلوک را فقط روی یک دیتا نود می نویسد و عملیات رپلیکا کردن توسط خود آن دیتا نود با دیتانودهای دیگر انجام می شود. یعنی کلاینت عملیات نوشتن رپلیکاهای مختلف را انجام نمی دهد.

در ضمن در اینجا هم مثل read، عملیات بصورت sequential است و پس از تکمیل نوشتن یک بلوک روی یک DataNode نوشتن بلوک بعدی شروع میشود و عملیات بصورت پارالل نیست. در اینجا هم باید برای افزایش سرعت از distcp برای نوشتن پارالل روی کلاستر HDFS استفاده کرد.

در صورتیکه عملیات نوشتن روی یک DN ناموفق باشد، کلاینت NameNode را از موضوع مطلع می کند و بلوک ناموفق را مجدد به اول صف نوشتن خود منتقل می کند تا چیزی از دست نرود و مجدد آنرا روی یک DataNode دیگر می نویسد. در عمل امکان از کار افتادن چندین DN با هم بسیار کم است، اما اگر چنین اتفاقی هم بیافتد، عملیات write به همین صورت تا رسیدن به تعداد رپلیکا مورد نظر روی DN های سالم ادامه پیدا می کند.
برای اینکه روش تخصیص بلوک ها به نودها چگونه باشد، استراتژی های مختلفی وجود دارد که روش زیر استراتژی پیش فرض هادوپ است. البته می توان استراتژی های دیگر را هم انتخاب کرد.

روش قراردادن بلوک های دیتا در نودهای مختلف (default placement strategy)

همانطور که قبلا گفته شد، hdfs برای ایجاد redundancy و افزایش پهنای باند read، از هر بلوک بصورت پیش فرض 3 تا کپی روی نودهای مختلف قرار می دهد. این عدد پیش فرض را برای کل مجموعه می توان عوض کرد و همینطور برای هر فایل جداگانه هم می توان این عدد را مشخص کرد. به عنوان مثال می توان فایل های با اهمیت کمتر را با رپلیکا 2 (یعنی دو کپی از هر بلوک) و فایل های با اهمیت بیشتر را با رپلیکا بالاتر، مثلا 5 نگهداری کرد.

بصورت پیش فرض hdfs رپلیکاها را بصورت زیر روی نودها تقسیم می کند.
اولین رپلیکا (یعنی اولین نسخه از کپی بلوک) روی همان نودی که کلاینت روی آن قراردارد نگهداری می شود. اگر کلاینت خودش یک DN نباشد یک نود DN تصادفی انتخاب شده و بلوک روی آن نگهداری می شود.
دومین رپلیکا روی یک نود تصادفی انتخاب شده از یک راک دیگر، ولی در همان دیتاسنتر نگهداری می شود. البته سعی می شود از نودهایی که الان به شدت مشغول، یا پر هستند استفاده نشود.
سومین رپلیکا روی یک نود تصادفی دیگر، از همان رکی که رپلیکای دوم در آن نوشته شده است نوشته می شود.
اگر رپلیکاهای بیشتری موجود باشد آنها هم روی نودهایی که بصورت تصادفی انتخاب می شوند نوشته می شوند. البته سیستم سعی می کند تعداد رپلیکاها روی نودهایی که روی یک رک هستند تا حد ممکن کم نگه دارد.

این روش پیش فرض یک تعادل مناسب بین قابلیت اطمینان (چون رپلیکاها روی نودهای راکهای مختلف نوشته می شوند)، پهنای باند رایت (چون ترافیک حداکثر بین یک سوییچ جابجا می شود)، پهنای باند read (چون امکان خواندن هر سه رپلیکا از نودهای دو راک استفاده شده است) ایجاد می کند، و علاوه بر این توزیع بلوک مناسبی را در کل کلاستر ممکن می کند.

مدل coherency سیستم HDFS

coherency model برای هر فایل سیستم مشخص می کند که قابلیت data visibility برای عملیات خواندن و نوشتن آن فایل سیستم چگونه است.

در هادوپ مدل وابستگی به این صورت است که تمامی write هایی که روی فایل انجام می شوند، تا زمانی که sync() یا hflush() فراخوانی نشود یا اینکه فایل close() نشود قطعی نیستند. تنها وقتی که جواب این روتین ها با موفقیت برگردد آن قسمت از write قطعا روی کلاستر است و توسط بقیه کلاینت ها قابل read است. تناوب به کاربردن sync بسته به نوع اپلیکیشن دارد و باید با دقت انتخاب شود تا به کلاستر فشار نیاورد.

ابزارهای جانبی

از آنجا که بسیاری از کاربردها روی HDFS بین برنامه های مختلف مشترک هستند، ابزارهای مختلفی هم برای کار با آن طراحی شده اند. یکی از این ابزارها Flume است که برای انتقال فایل های داده بزرگ به HDFS استفاده می شود. به عنوان مثال از Flume می توان برای کپی کردن لاگ های یک مجموعه بزرگ وب سرور به یک کلاستر HDFS برای آنالیز بعدی استفاده کرد.

یک ابزار دیگر هم Scoop است که برای انتقال فایل های بزرگ structured Data مثل فایل های RDBMS ها (بانک های اطلاعاتی) به کلاسترهای HDFS استفاده می شود.
یک ابزار مهم دیگر، distcp است. همانطور که قبلا گفته شد، عملیات read و write بصورت عادی در hdfs بصورت تناوبی است و بنابراین مزایای سرعت زیاد کار پارالل را ندارد. distcp خودش بصورت که جاب map/reduce پیاده سازی شده است و بنابراین به هر اندازه ای که کلاستر MapReduce بزرگ شود، distcp هم می تواند کارآمد شود. بصورت عادی از distcp هر کجا که نیاز به انتقال حجم بزرگی از دیتا به داخل کلاستر hdfs یا بیرون کشیدن از آن باشد استفاده میشود، مثلا وقتی که قرار است دیتا بین دو کلاستر hdfs جابجا شود. بصورت عادی هر map یک بخش 256 مگابایتی از دیتا را کپی می کند و ماکزیمم تعداد map به ازای هر نود هم 20 تا است. بنابراین وقتی یک فایل 1000 گیگابایتی روی یک کلاستر با 100 نود کپی می شود، 20000 مپ تولید می شود که هر کدام 512 مگابایت را کپی می کنند. برای اینکه بالانس داده روی کلاستر از بین نرود باید تعداد مپ ها همیشه از تعداد نودهای کلاستر بیشتر باشد. بالانس کلاستر به این معنی است که روی یکسری نود تجمع دیتا بیشتر از بقیه نباشد. به هر حال اگر بالانس کلاستر به هم بخورد هم بعدا می توان مجددا با ابزار balancer آنرا بالانس کرد.

نتیجه گیری

با بررسی انجام شده مشخص می شود که یک کلاستر hdfs اصلا به عنوان محیط ادیت برای کار ادیت یک سری فایل ویدئویی مناسب نیست و اصلا با این هدف هم طراحی نشده است. اما در آرشیو ویدئو hdfs می تواند گزینه مناسبی باشد. در این حالت می توان با راه اندازی یک کلاستر hdfs و ایجاد یک سری پروکسی برای دسترسی به آن، فایل های ویدئویی آرشیوی که هم بزرگ هستند و هم بعد از وارد آرشیو شدن، دیگری فقط به عنوان منبع مورد استفاده قرار گرفته و تغییر نمی کنند را در اختیار کاربران قرار داد. علاوه بر این اگر کلاینت hdfs داخل خود برنامه asset management یا newsroom گنجانده شود، نیاز به سرورهای پروکسی هم از بین رفته و کلاینت ها می توانند مستقیما با کلاستر آرشیو تماس بگیرند.

تنها نکته ای که در اینجا باقی می ماند، عدد رپلیکا 3 است. تحقیقات گوگل وبقیه نشان داده است معمولا نگهداری 3 رپلیکا برای حفاظت داده کفایت می کند (البته این جایگزینی نوارهای lto به عنوان مدیای آرشیو offline نمی شود، بلکه بخش tape library را که قرار بوده بصورت near line باشد و نرم افزارهای جانبی آن مانند XenData را حذف میکند)، اما به هر حال نگهداری رپلیکا 3، به معنی 3 برابر ظرفیت دیسک است که باید برای آن چاره اندیشی کرد.