اسکیل دیتابیس‌ها به وسیله‌ی شاردینگ/Sharding

شاردینگ روشی است برای تقسیم اطلاعات یک دیتابیس بین گره‌های کوچک که داده ها به طور مجزا در هرکدام از این گره ها ذخیره و بازیابی میشود.به طور کلی میتوان آن را نوعی پارتیشن بندی برای داده‏‎های موجود در دیتابیس درنظر گرفت.که به افزایش کارایی و همزمانی(parallelism) برای اجرای یک کوئری که به افزایش بسیار چشمگیر زمان پاسخگویی می‌انجامد، در واقع یک پیاده سازی از مفهوم لودبالانسینگ است.

برخلاف روش Master-Slave که یک کپی از تمام داده‌ها در تمامی گره‌ها موجود است، در شاردینگ فقط تکه‌هایی از داده ها در هر گره(شارد) موجود است که این روش تقسیم بندی باعث ایجاد مزایا و معایبی شده است که اگر به جا استفاده شود در عملکرد سیستم تاثیر بسزایی خواهد داشت.

شاردینگ از نوع اسکیل افقی( horizontal scaling ) محسوب میشود و اسکیل افقی زمانی انجام میشود که سیستم به حدی رسیده باشد که اسکیل عمودی(vertical scaling)(افزایش منابع یک سرور به کارایی آن کمک نکند یا به نهایت ظرفیت برسد) در نتیجه بار بین چند ماشین مستقل تقسیم میشود تا بتواند پاسخگوی نیازهای سیستم باشد.پس تا زمانی که سیستم شما دچار مشکل نشده و اسکیل عمودی قابل انجام است و لارج دیتا ندارید سراغ اسکیل افقی نروید.

شاردینگ انواع مختلفی دارد و بسته به نوع دیتابیس ای که دارید ممکن است روشها متفاوت باشد، انتخاب نوع شاردینگ بستگی به این دارد که سیستم شما چه نیازمندیهایی دارد،اگر نوع و کلیدشاردینگ به اشتباه انتخاب شود قطعاً سیستم شما دچار ضعف در خواندن و هم نوشتن خواهد شد.

در اینجا به دو نوع مرسوم شاردینگ میپردازم:

  • شاردینگ برحسب بازه(Range-based Sharding) بیشتر برای اسکیل خواندن(Read Scale) استفاده میشود.
  • شاردینگ برحسب هش(Hash-based Sharding) بیشتر برای اسکیل نوشتن(Write Scale) استفاده میشود.
    استفاده از «بیشتر» برای این است که ممکن است هرکدام برای کاربرد دیگر هم استفاده میشوند و در هردو (R/W) هم تاثیر گذار هستند.

شاردینگ برحسب بازه:

شمای یک شاردینگ بازه‌ای
شمای یک شاردینگ بازه‌ای


در این نوع تقسیم بندی هر کدام از داده‌ها توسط (روتر/دیسپاچر) دیتابیس برحسب بازه‌ی تعیین شده در کلید شاردینگ در سروری که شامل آن بازه میشود ذخیره میشود. در تصویر بالا میبینید که شاردینگ بین سه شارد برحسب مقدار X که همان کلید اجرایی شارد است انجام شده است.

ویژگی‌های یک کلیدشاردینگ بازه‌ای مناسب:

  • گستردگی داده‌ها و یا کاردینالیتی بالا به طوری که کلید تمامی شاردها را شامل باشد.اگر کاردینالیتی شما در کلید شارد N باشد شما نمیتوانید بیشتر از N شارد داشته باشید.(اگر کاردینالیتی کم باشد برای جبران آن از ترکیب دو یا چند کلید استفاده کنید)
  • فرکانس/بسامد بین داده‌ها کم باشد.اگر نرخ تغییر داده ها زیاد باشد در یک شارد صف نوشتن ایجاد میشود و دیگرشاردها بیکار میمانند در نتیجه میبایست متعادل ترین حالت را انتخاب کرد.
  • نباید به طور یکنواخت تغییر کند. مثل Auto Increment ها و سری های زمانی 1,2,3,4,5... تنها این نوع انتخاب کلید برای OLAP/ Read only استفاده میشود که عملیات نوشتن مهم نیست. درصورتیکه نوشتن مهم باشد این نوع انتخاب باعث میشود در هربازه فقط نوشتن روی یک شارد متمرکز شود.

در زمان نوشتن داده‌ها اگر کلیدشارد auto increment/افزایش خودکار باشد تا زمانیکه شارد اول پر نشود مابقی شاردها بیکار خواهند ماند در نتیجه فشار نوشتن فقط روی یک سرور قرار میگیرد و از این رو نوشتن اسکیل نمیشود.

در زمان خواندن اگر شرطی برای تعیین کلید شارد X داشته باشیم فقط شاردهای مربوط به همان بازه پاسخگوی کوئری خواهند بود و از آنجایی که شاردها به صورت مستقل بین داده‌های کوچکتری کوئری میگیرند عملیات خواندن به صورت موازی سریعتر انجام خواهد شد.

شاردینگ برحسب هش:

شاردینگ برحسب هش
شاردینگ برحسب هش

یکی از مزایایی که عموم توابع هش درپی دارند از بین بردن محدودیت اندازه کلید شارد هست.

به طور کلی هدف از شاردینگ برحسب هش توزیع یکنواخت و بدون محدودیت داده ها در سرتاسر شاردهای موجود است و از بین بردن محدودیت تعداد شارد برحسب کاردینالیتی در شاردینگ بازه ای است، همچنین محدودیت تغییر یکنواخت (افزایشی/کاهشی) کلید شارد را هم از بین می‌برد.

برای مثال فرض کنیم40,41,42,... را که کلید شاردهستند را میخواهیم ذخیره کنیم اگر از رنج استفاده شود تمام عملیات در یک شارد صورت میپذیرد ولی اگر تابع هش ما MD5 باشد هش این 3 به ترتیب زیر خواهد شد

D645920E395FEDAD7BBBED0ECA3FE2E0

3416A75F4CEA9109507CACD8E2F2AEFC

A1D0C6E83F027327D8461063F4AC58A6

اگر فقط حرف اول رشته هش بعنوان شاخص در نظر گرفته شود. میبینیم که این 3عدد که پشت سرهم هستند هریک در شارد مجزایی ذخیره میشوند.

توابع هش رنج خاصی را ارائه نمیدهند اگر شما بخواهید در یک بازه در کلید شارد یک کوئری بگیرید روتر نمیتواند تشخیص دهد بازه مورد نظر در کدام شارد است و در تمام شاردها کوئری را اجرا میکند،از این رو در خواندن به مراتب بازدهی کمتری به نسبت نوشتن دارند.


چگونگی انتخاب کلید شارد مناسب

به طور خلاصه کلیدی که باعث توزیع بار یکنواخت (چه برای نوشتن یا خواندن) بین شاردها شود یک کلید مناسب است.یعنی اگر ما N تعداد داده داشته باشیم و S شارد در بهینه ترین حالت میبایست در هر شارد N/S داده ذخیره شود.

اگر نتوانستید کلید شارد خوبی بدست آورید از کلیدهای ترکیبی (در صورتی که دیتابیس شما پشتیبانی کند) استفاده نمایید.

اگر برای منظور (OLAP) و کارهایی که شما انبوهی از داده ها را وارد یک دیتابیس کرده و صرفاً از آن گزارش تهیه میکنید میخواهید شاردینگ داشته باشید میتوانید تعداد داده‌ها را تقسیم بر شاردها کرده و هر شارد را به ترتیب کوچکتر یا بزرگتر پر کنید در این روش نوشتن اسکیل نمیشود ولی خواندن به شدت افزایش پیدا میکند.

اگر دیتابیس زیرفشار رایت است (OLTP) میتوانید از هش استفاده کنید که به طور توزیع شده هر عملیات نوشتن را در یک شارد انجام میدهد و باعث موازی شدن نوشتن میشود ولی به طور کلی بازدهی بالایی برای گزارش گیری و خواندن ندارد.


نکته اکثر موارد بالا در مورد پارتیشن بندی در یک نُد هم صدق میکند.
دیتابیسهای SQL و No SQL در شاردینگ تفاوتهایی دارند ولی در اصول کلی میتواند آنها را یکسان قلمداد کرد، اکثر دیتابیسهای مطرح از شاردینگ به طور پیشفرض پشتیبانی میکنند، برای مثال:
MySQL , PostgreSQL,MongoDB ...

مشکلات شاردینگ

نگهداری بسیار پیچیده از هر جهت مدیریتی

منطق اپلیکیشن استفاده کننده باید بسیار دقیق و هماهنگ باشد وگرنه کارایی از دست میرود.

بکاپ گیری بسیار سخت

امکان دیتالاست در صورتیکه در بکاپ‌گیری هر شارد مشکلی پیش بیاید

و...


راه‌های دیگری برای گسترش پذیر کردن بانکهای اطلاعاتی وجود داره که اگر فرصت شد در ادامه خواهم گفت.


اگر ایرادی در نوشتار یا ایراد فنی میبینید خوشحال میشم تذکر بدید!