در باب scale افقی و عمودی MySQL و مشتقاتش!

اگر در سال ۱۹۹۰ زندگی میکنید که هیچ اما اگر در سال دوهزار و چند هستید و در حال توسعه نرم‌افزار درصدی باید احتمال بدید که ممکنه نرم‌افزار شما توسط افراد زیادی استفاده بشه و این در برخی مواقع می‌تونه شما رو به دردسر بندازه. اینکه بدونید چه راهکارهایی وجود داره و در این مواقع بر حسب نیازتون بتونید تصمیم درستی بگیرید کلی از استرس شب امتحان کاهش می‌ده.

در برخی سناریوهای بالا رفتن لود سرورها گلوگاه یا Bottleneck ما دیتابیس می‌تونه باشه. از اونجایی‌که هنوزم بسیار از توسعه‌دهنده‌ها و شرکت‌ها به دلایل مختلفی تمایل به استفاده از دیتابیس‌های relational دارند و MySQL و سایر رفقا هم از جمله دیتابیس‌های پر طرفدار هستند، در این مقاله قصد دارم سرتونو با روش‌هایی که می‌شه MySQL رو Scale درد بیارم و یه نگاه کلی به این مقوله بندازیم. این مقاله تخصصی وارد هر فاز نمیشه و صرفا به کلیات ماجرا اشاره می‌کنه پس اگر نا امید شدید و قصد دارید بدونید تهش چی می‌شه و تخصصی‌تر ماجرا چیه می‌تونید با من تماس بگیرید؟

(من هنوز معادل درستی برای Scale پیدا نکردم تو حوزه نرم‌افزار. توسعه به خوبی معنا رو نمی‌رسونه و خب ابهام بر انگیزه و مقیاس دهی یا مقیاس پذیری و مشابهاتش هم ابهام ایجاد می‌کنه. بنابراین از خود کلمه به انگلیسی استفاده می‌کنم).




خب در ابتدا از مزایای Scaling بگیم:

  • تعداد بیشتری از کاربران را می‌تونید پشتیبانی کنید.
  • پرفرمنس بهتری به کاربران فعلی می‌تونید ارائه کنید.
  • حجم بیشتری از داده‌ها را می‌تونید ذخیره کنید.
  • دسترس پذیری سیستم (یا همون Availability) را دچار بهبود خواهد کرد.
  • این امکان را خواهید داشت که بانک اطلاعاتی را اصطلاحا Cross Datacenter Replicate کنید.

البته موارد دیگه‌ای هم می‌تونه باشه که من فراموش کردم بهش اشاره کنم (خب شما اشاره کنید!) ، پس به این نتیجه می‌رسیم Scaling خوشمزست. اما....

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

  • هزینه سخت افزار اولین هزینه‌ای هست که به مجموع هزینه‌های شما اضافه می‌شه.
  • پیاده سازی این ساختارها معمولا پیچیده و زمان بر هست و هزینه زمانی و مالی نگه‌داری این زیرساخت را هم در نظر باید گرفت.


در مورد نگه‌داری این ساختارها ذکر این نکته ضروریه که اگر دانش فنی لازم را ندارید و به افراد متخصص دسترسی ندارید ممکنه در پیاده سازی موفق باشید اما در زمان Disaster درمان و رفع مشکلات این ساختارها به مراتب پیچیده‌تر، تلخ‌تر و دردناک‌تره پس قبل از پروداکشن کردن همچین ساختارهایی به همه‌ی جوانب کار فکر کنید یا که چند شب ممکنه از خواب محروم بشید. (همانا خواب خط قرمز ماست، اصلا روایت داریم که طوری سیستم رو پیاده کنید که شب بتونید راحت بخوابید. حالا خود دانید!).




خب بریم سر وقت آپشن‌هایی که داریم برای Scale کردن.

شماره ۱ : Vertical Scaling

اسمش روشه و آسونترین روشه و عموما هم شامل افزایش رم و سی پی یو هست و اگر دیسک جدید اضافه کنید یه خورده اضافه کاری و پارتیشن بازی هم دارید (که حتما دست اینکاره بسپارید اگر خودتون بلد نیستید و روی پروداکشن با پارتیشن شوخی نکنید). در مورد دیسک هم الان که SSD ها ارزون‌تر شدن بیخیال هر نوع دیسک سختی بشید و برای دیتابیس حتما از SSD استفاده کنید.

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

شماره ۲: Scaling Horizontally

روش Active-Passive:

در این روش شما دوتا instance دارید و تمام کوئری ها راهی Active میشه و عملیات نوشتن به صورت خودکار به سرور Passive ارسال میشه. در این روش شما قدرت پردازشی بیشتری به دست نمیارید و تنها در زمانی که سرور Active دچار اختلال بشه به سرعت می‌تویند سوییچ کنید به سرور Passive و اونو تبدیل به Active کنید و بعد در زمان مناسب سرور را تعمیر کنید. فرایند سوییچ کردن از طریق لود بالانسر یا VIP امکان‌پذیره یا روش‌های دیگه‌ای که احتمالا من بلد نیستم.

روش Master-Slave:

نه نه اون نیست! تو این روش ما حداقل دو تا Instance داریم. یکی Master و به تعداد دلخواهی Slave میتونیم داشته باشیم. کوئری های نوشتن به Master و کوئری های خواندن روانه Slave ها میشن. قاعدتا Master تمام عملیات‌های نوشتن را replicate می‌کنه به Slave ها.

  • تو این روش محدودیتی در تعداد Slave ها نیست اما فقط یک Master میتونید داشته باشید.
  • برای اپ‌هایی که Heavy read هستن کارایی خوبی داره.
  • برای رفع Network bottleneck ها می‌تونه کارآمد باشه.
  • در این روش اپ باید بتونه روتینگ کوئری‌ها را انجام بده. (برای مثال لاراول این امکان رو داره و سایر فریمورک‌ها هم باید داشته باشن و البته در فریمورک‌های مدرن پیاده سازی این امکان خیلی کار سختی نیست)
  • نود Master را تنها به صورت Vertical میتونید Scale کنید.


موردی که احتمالا به ذهنتون رسیده در رابطه با Multi Master replication هست. در این مقاله به این موضوع اشاره نمی‌کنم اما مشکلات متعدد این روش باعث شده گزینه‌ی خوبی برای Scaling نباشه. در محیط آزمایشگاهی به خوبی جواب می‌ده اما به خاطر اینکه برخی عملیات ها در این روش خودکار نیستن و به سادگی سرورها از sync خارج می‌شن و sync مجدد هم باید دستی صورت بگیره این روش ایده‌آل نیست.

روش Cluster:

این ویژگی اگر اشتباه نکنم اولین بار در MySQL 5 پا به عرصه‌ی وجود گذاشت و سپس در طول این سالها بهبود خوبی پیدا کرد. تو این روش مشکلات روش‌های بالا عموما وجود نداره و کلاستر کوئری‌ها را بین سرورهای متعدد پخش می‌کنه و مشکل SPOF رو حل می‌کنه و خب تا حد نامحدودی میتونید سرور اضافه کنید(البته در مقام عمل واقعا نامحدود نیست). آنچه که MySQL معرفی کرده از سه بخش سرور ذخیره ساز، پردازشگر کوئری و نود مدیریتی تشکیل شده. هر کلاستر باید حداقل دارای ۲ نود از هر بخش باشه یعنی ما حداقل به ۶ سرور نیاز داریم. (با سه تا سرور هم میشه پیاده سازی کرد که SPOF خواهید داشت)

  • این مکانیزم میتونه HA را برای شما به ارمغان بیاره.
  • پرفرمنس خوبی داره.
  • برای اپ‌های Heavy write مناسبتره.
  • برای هر نود میشه اجزایی که لازمه مثلا فقط رم یا سی پی یو را برای حسب نیاز اضافه یا کم کرد.
  • بین سرورها Synchronous replication دارید.
  • رم بسیار زیادی لازم خواهید داشت در این روش.
  • پیچیده است.

البته در دوران نوین‌تر ما Galera Cluster هم داریم که با اینکه تنها روی انجین های InnoDB و XtraDB کار میکنه و کامیونیتی بیشتر از Galera Cluster استفاده میکنند و تمایل این سمت بیشتره . همین موارد رو کم و بیش داره Galera و خب پشتیبانی Perconna , MariaDB رو داره که این روزها من به خود MySQL ترجیح میدمشون.


روش Sharding:

این روش در NoSQL ها به شدت مورد علاقه‌ی منه و البته تا زمانی‌که واقعا دیتاست بزرگی ندارید نیاز نیست دست به دامن این روش بشید. در زمان مناسب حین اینکه اشک از چشمانتون روانه‌است خودتون متوجه نیازتون به این روش خواهید شد. Sharding روش‌های مختلفی داره اما ساده ترین حالتش این میشه که شما یه تیبل خیلی بزرگ رو تکه تکه می‌کنید و در جاهای مختلف ذخیره می‌کنید. موردی که اشاره کردم Horizontal table partitioning هست عملا در MySQL‌جات و همونطور که اشاره کردم فقط در زمان بیماری حاد استفاده می‌شه. عمیقا پیشنهاد میکنم بعنوان آخرین راه حل این روش را در نظر بگیرید. (سری که درد نمیکنه چی؟ دقیقا...)

  • کارآمد برای لود بسیار بسیار بالای دیتابیس.
  • روشی مناسب برای زمانی که جوین بین Shard ها ندارید.
  • کارآمد بودن این روش تا حد زیادی وابسته به مدلی هست که Sharding را انجام میدید.
  • پیاده سازی بسیار بسیار پیچیده.
  • دسترس پذیری را بهبود میده و اگر بخشی از شبکه fail بشه شما تنها بخش کوچکی از داده‌هاتون ممکنه از دسترس خارج بشه.

(این روش را من خودم تا حالا پیاده سازی نکردم و نیاز نشده و امیدوارم نشه. در SQL ها این روش یکم زیادی ترسناکه هنوز برام. اگر تجربه‌ی این کارو دارید دوست دارم بدونم چطور انجام دادید!)




موردی که در انتها لازمه بهش اشاره کنم در رابطه با Scaling اینه که اپ شما باید تا حدی بر حسب مدلی که شما دیتابیس را Scale میکنید هماهنگ بشه خصوصا برای زمان failure ها باید استراتژی مناسبی داشته باشید که لازم نباشه اگر نصف شب اتفاقی بیوفته سریعا خودتونو برسونید پای سرورها. (معلومه داغ دیده‌ام نه؟!)

خلاصه که Scaling با اینکه مبحث دلچسب و جالب و با کلاسی هست برای بررسی و پیاده سازی و حتی کلاس گذاشتن در مجامع فنی :)) اما دردسرهای خاص خودشو هم داره.

امیدوارم که به اندازه کافی روزتونو با این مطلب خراب نکرده باشم.

مثلا Scale طور...
مثلا Scale طور...