در طی سری جلساتی که به پیشنهاد دوستان برگزار شد، توفیقی حاصل شد که کمی با HBase، نحوهی کارکرد و ساختار داخلی آن آشنا شوم. در این متن، برداشت خودم را از HBase به اشتراک میگذارم.
در یک جمله، HBase پایگاهدادهای در چارچوب هادوپ است که مقیاسپذیری و توزیعشدگی را برای دادههای بزرگ فراهم میکند.
ساختار دادهی HBase شباهت زیادی به Google big table دارد که دسترسی تصادفی را به اطلاعات فراهم میکند. این ساختار داده از تعدادی جدول تشکیل شده و هر جدول دارای تعدادی سطر است. هر سطر از یک کلید تشکیل شده و راه اصلی برای دریافت اطلاعات یک سطر، استفاده از کلید آن میباشد. هر سطر میتواند شامل چندین column family بوده و هر column family هم میتواند صفر یا چند column qualifier داشته باشد. در این ساختار، column familyها باید در تعریف جدول مشخص شده باشند (البته مکانیزم مجزا برای اضافهکردن column family بعد از ایجاد جدول نیز هست) ولی column qualifier ها میتوانند در حین کار با جدول کم یا زیاد شوند. برای مثال، جدول زیر را در نظر بگیرید:
این جدول شامل سه سطر و هر سطر دارای دو column family است. در حال حاضر هر column family دو qualifier دارد؛ ولی با اجرای دستوری مانند ذیل میتوان به راحتی برای سطر ۱ یک column qualifier جدید ایجاد کرد:
put ’employee’, ‘1’, ‘personal data:lastname’, ‘rajvash’
البته نحوهی ذخیرهسازی این جدول به گونهای است که صرفا فضا برای دادههای موجود مصرف شود و اگر به عنوان مثال، یک سطر صد column qualifier داشت،برای بقیهی سطرهای جدول به این اندازه حافظه مصرف نشود.
برای اطلاعات بیشتر در مورد نحوهی ذخیرهسازی، میتوانید به این دو منبع مراجعه کنید:
Understanding HBase and BigTable
توضیح ساختاری HBase
HBase در قالب تعدادی نود اجرا میشود که هر نود میتواند دو نوع داشته باشد:
- HBaseMaster که وظیفهی کنترل کردن کلاستر را به عهده دارد و میتواند چندین slave داشته باشد.
- HRegionServer که مدیریت دادهها و Region ها را به عهده دارد.
در واقع، HBase برای ذخیرهسازی یک جدول، آن را به تعدادی Region تقسیم میکند و Region های مختلف روی RegionServer های مختلف ذخیره میشوند. هر Region از تعدادی سطر تشکیل شده که کلیدهای این سطرها پشت سر هم (از نظر الفبایی) هستند. به عنوان مثال یک جدول میتواند در سه Region به صورت ذیل ذخیره شود:
Region1: a-h, Region2: ha-n, Region3: na-z
مکانیزم تعیین کلید
همونطور که گفته شد، HBase برای تقسیم دادهها از کلیدها استفاده میکند که به صورت الفبایی مرتب شدهاند. در نتیجه اگر انتخاب کلیدها به گونهای باشد که در یک بازهی کوتاه زمانی عملیاتهای نوشتن روی یک region انجام شود، کارآیی کلاستر کم خواهد شد. به همین علت انتخاب کلید از اهمیت ویژهای برخوردار است و بایستی کلیدها را به گونهای تعیین کرد که بار تا حد امکان تقسیم شود. مثلا اگر کلید ما timestamp باشد، باعث میشود همیشه یک region شلوغ باشد. به همین علت توصیه میشود کلید را reverse و ذخیره کنیم تا بار به طور مناسب روی region های مختلف پخش بشود.
پ.ن: همین نکتهی ریز و عدم هماهنگی بین دو تیم باعث شد دقیقا وقتی که من در مسافرت بودم، در کدی که چند ماه بود کار میکرد، سر یک region بار زیادی بریزد و ۱۰-۱۲ ساعت وقت من را در مسافرت بگیرد تا بفهمم علت کندی، hotspot شدن یک region و پیش آمدن یک حالت خاص بوده که کلیدها به طور متوازن توزیع نمی شدند :D
در چه مواقعی سراغ HBase برویم؟
- اگر داده به میزان کافی ندارید، سراغ HBase نروید!
- برای حجم داده در حد چند میلیون رکورد، RDBMS ها بهتر هستند.
- اطمینان حاصل کنید قابلیتهایی مانند join در RDBMS ها را نیاز ندارید و مدل دادهی HBase می تواند نیاز شما را پاسخگو باشد.
- سختافزار کافی داشته باشید! HBase در محیط عملیاتی حداقل به ۵ نود احتیاج دارد.
مکانیزمهای HBase برای فراهم کردن سرعت بالا چیست؟
- استفادهی مناسب از HDFS
HDFS یا همان Hadoop Distributed File System یک فایلسیستم توزیعشده در چارچوب هادوپ است. HDFS موارد متعددی مانند replication و cluster rebalancing را پشتیبانی میکند ولی به صورت صریح گفته شده که یک فایلسیستم عمومی نیست؛ برای فایلهای بزرگ بهینه شده و برای جستجوی سریع مناسب نیست. از طرفی، HBase برای ذخیرهسازی دادههای خود از HDFS استفاده کرده و جستجوی سریع ارائه میدهد! این تفاوت از اینجا ناشی میشود که HBase به جای ذخیرهسازی هر سطر به عنوان یک فایل، سطرهای مختلف یک جدول را در کنار هم در یک فایل بزرگ ذخیره میکند که اندازه آن برای ذخیرهسازی در HDFS مناسب است. همچنین، HBase این فایلها را به صورت ساختارمند تهیه میکند تا بتواند lookup های مورد نظر را به سرعت روی آن انجام دهد. - نوشتن روی حافظه
برای بالابردن کارآیی، هنگام نوشتن دادهی جدید، دادهها مستقیما روی HFile ها ( فایلهای ذخیرهشده روی HDFS) نوشته نمیشوند، بلکه روی حافظهای به نام Memstore ذخیره و در صورت لزوم بازیابی میشوند. این کار باعث بهبود سرعت میشود. همچنین برای اینکه دادهها قبل از نوشتن روی Memstrore از دست نروند، لاگ درخواست روی فایل
WAL (مخفف Write Ahead Log) ثبت میشود. این Memstore ها به صورت دورهای (مثلا با محدودیت زمانی، حجمی یا … ) در فایلهای مجزا ذخیره میشوند.
- مکانیزم minor compaction
در این فرآیند، چند HFile مربوط به یک column family که نزدیک به هم هستند ادغام میشوند. البته همهی HFile ها نه به یک HFile، بلکه به تعداد کمتری HFile تبدیل میشوند. - مکانیزم major compaction
در این فرآیند که به صورت پیشفرض هر ۷ روز یکبار انجام میشود، چندین HFile به یک HFile واحد تبدیل میشود تا در نهایت به ازای هر Column Family یک HFile وجود داشته باشد.
فرآیندهای مختلفی مانند حذف سطرهای پاک شده، حذف نسخههای منقضی شده، compaction و … نیز بلافاصله انجام نشده و در طی Major Compaction انجام میشود تا سرعت کلاستر کاهش پیدا نکند. همچنین این فرآیند طوری انجام میشود که در هر لحظه تعداد کمی Region درگیر Major Compaction شوند تا کلاستر بتواند پاسخگو باقی بماند.
- ذخیرهسازی مرتب دادهها
دادهها در هر HFile به ترتیب ذخیره میشوند، به این معنی که در هر فایل، اطلاعات ابتدا به ترتیب کلیدها ذخیره میشوند و سپس برحسب timestamp (موقع درج هر داده یک timestamp زمان حال به داده نسبت داده میشود)، مانند شکل زیر. این کار باعث میشود تا بازیابی اطلاعات سریعتر انجام شود.
راههای دسترسی به داده در HBase
طبعا راحتترین راه دسترسی به دادهها در HBase از طریق کلید هر سطر است. با این وجود، مکانیزم دیگری به نام scan نیز در HBase تعبیه شده که میتوان با اسکن کردن طیفی از دادهها و حتی مشخص کردن فیلترهای متنوعی به دادهها دسترسی داشت. مکانیزم scan به صورت عمومی عملیات پرهزینهای است و شناختن مکانیزم داخلی آن میتواند به طراحی مناسب مدل داده و استفادهی بهینه از HBase کمک کند.
در واقع، هر scan به صورت طبیعی به تمامی regionهای یک جدول (در حالت عادی، کل کلاستر) ارسال و جوابها برگردانده میشود. این کار در حالت عمومی منجر به خوانده شدن همه HFile ها با هزینهی بالا خواهد شد.
حال اگر در تنظیمات اسکن بازه زمانی مشخص شده باشد، با توجه به نحوهی ذخیرهسازی دادهها در هر فایل، خواندن هر فایل در هر region با سرعت بالاتری انجام میشود و اگر در تنظیمات اسکن کلید شروع و پایان مشخص شده باشد، صرفا همان region هایی که حاوی کلیدهای مشخص شده هستند درگیر شده و سرعت انجام اسکن بالاتر خواهد رفت.