دسترسی پذیری بالا برای MySQL و MariaDB: مقایسه رپلیکیشن مستر-مستر با گالرا کلاستر
گالرا کلاستر (Galera Cluster) یکی از راهکارهای جدید پیادهسازی دسترسی بالا (High Availability) برای دیتابیسهای MySQL و MariaDB است که نسبت به رپلیکیشن MySQL پیشینه کوتاهتری دارد. رپلیکیشن (Replication) MySQL، که بصورت درونی (native) از نسخه MySQL v3.23 پشتیبانی میشود، بصورت master-slave طراحی شده است اما با تغییر تنظیمات میتوان آن را بصورت مستر-مستر (master-master) هم پیادهسازی کرد. گرچه پیادهسازی آن نسبتا آسان است و برای بعضی کاربردها جواب میدهد، اما محدودیتهایی هم دارد. در طرف دیگر، گالرا کلاستر تکنولوژی متفاوتی است پیادهسازی و مدیریت آن نیازمند دانش مروبط به خودش است.
آیا مزایای کلاستر MySQL گالرا استفاده از آن را بجای رپلیکیشن MySQL توجیه میکند؟ در این مطلب گالرا کلاستر را با رپلیکیشن درونی دیتابیس MySQL مقایسه میکنیم.
رپلیکیشن دیتابیس چیست؟
بگذارید قبل از شروع مقایسه، مفاهیم مربوط به مکانیزم پیادهسازی رپلیکیشن در این ۲ راهکار را توضیح دهیم. بصورت کلی، هر تغییری در پایگاه داده MySQL یک رویداد بصورت فایل باینری ایجاد میکند. بعد از فعالسازی رپلیکیشن، این رویداد به نودهای همتا فرستاده میشود تا با اعمال آن با نود اصلی سینک شوند.
رپلیکیشن MySQL
نمودار زیر روند ارسال اطلاعات از نود مستر به نود رپلیکا بعد از انجام یک تراکنش موفق در دیتابیس MySQL را نشان میدهد.
ابتدا رویداد به صورت باینری در لاگ باینری نود مستر MySQL ذخیره میشود. سپس نود یا نودهای slave بوسیله slave_IO_thread رویدادهای باینری را از لاگهای نود مستر پول (pull) کرده و در لاگ relay خودشان ذخیره میکنند. سپس slave_SQL_thread این رویدادها را خوانده و بصورت آسنکرون (Asynchronous) در پایگاه داده خود اعمال میکنند. با توجه به ذات آسنکرون این رپلیکیشن، تضمینی وجود ندارد که نود رپلیکا، در همان لحظهی انجام تراکنش در نود مستر، اطلاعات جدید را اعمال کند.
به صورت ایدهآل نودهای slave در رپلیکیشن دیتابیس MySQL با تنظیمات read_only=ON یا super_read_only=ON بصورت فقط خواندنی کانفیگ میشوند تا ارسال دستورات write تصادفی به این نودها، باعث ایجاد تناقض بین نودهای مستر و رپلیکا نشود. این ناهماهنگی بین نودهای رپلیکیشن مخصوصا هنگام failover ممکن است باعث بروز خطا شود. ولی در رپلیکیشن master-master باید آپشن فقط خواندنی در نود مستر دوم غیرفعال باشد تا امکان پردازش نوشتنهای همزمان بین نودهای مستر وجود داشته باشد. در این سناریو با استفاده از آپشن CHANGE MASTER در مستر اول این امکان فراهم میشود تا بصورت چرخشی نود مستر اول هم با نود مستر دوم سینک شود.
رپلیکیشن گالرا کلاستر
نمودار زیر روند ارسال اطلاعات از یک نود به نود دیگر بعد از انجام یک تراکنش موفق در کلاستر گالرا را نشان میدهد.
در این سناریو رویدادها در یک writeset کپسوله شده و از نود مبدا به بقیه نودها برادکست میشوند. هر کدام از نودها بستههای دریافتی را بررسی کرده و در صورت تایید آنها را بصورت آسنکرون اعمال میکنند. در نهایت همه نودها بعد از بررسی و اعمال تغییرات، یکپارچه خواهند شد. این روند بصورت لاجیکال سنکرون (Synchronous) است اما عملیات نوشتن و اعمال تغییرات بصورت مستقل (و در نتیجه آسنکرون) و با تضمین یکپارچگی نهایی در رپلیکاهای مختلف انجام میشود.
جلوگیری از تصادم کلید اصلی در کلاستر MySQL
برای پیادهسازی رپلیکیشن مستر-مستر در دیتابیس MySQL باید افزایش خودکار کلیدهای اصلی پایگاه داده را طوری تنظیم کرد تا به مشکل تصادم کلید اصلی (Primary Key Collision) بین نودهای مستر برنخوریم؛ به این صورت که کلیدهای اصلی در نودهای مختلف به گونهای افزایش یابند که با هم همپوشانی نداشته و در نتیجه یک شماره دو بار استفاده نشود. این کانفیگ باید براساس تعداد نودهای مستر در کلاستر، به صورت دستی تنظیم شود. در زیر نمونهای از تنظیمات نودهای مستر در رپلیکیشن مستر-مستر MySQL (در فایل my.cnf) را مشاهده میکنید.
Master1: log-slave-updates auto_increment_increment=2 auto_increment_offset=1 Master2: log-slave-updates auto_increment_increment=2 auto_increment_offset=2
مقدار auto_increment_increment باید در هر نود مستر برابر با تعداد کل مسترهای کلاستر باشد. متغیرهای auto_increment_offset هم باید با مقادیر منحصر به فرد در هر پایگاه داده مستر تنظیم شوند.
به طریق مشابه گالرا کلاستر هم راهکاری برای جلوگیری از تصادم کلیدهای اصلی در دیتابیس دارد؛ در این راهکار مقدار افزایش خودکار کلید اصلی بصورت خودکار و با استفاده از متغیر wsrep_auto_increment_control انجام میشود. در صورتی که این متغیر یک باشد (که بصورت پیشفرض هست) گالرا کلاستر متغیرهای auto_increment_increment و auto_increment_offset را بصورت خودکار و براساس تعداد نودهای مستر تنظیم میکند. مسلما در کلاسترهای master-slave این متغیر باید غیرفعال یا off باشد. جدول زیر نمونهای از مقادیر کلید اصلی در یک کلاستر MySQL با ۳ نود مستر را نشان میدهد.
Auto increment value | Auto_increment_offset | Auto_increment_increment | Node |
1, 4, 7, 10, 13, 16… | 1 | 3 | Node 1 |
2, 5, 8, 11, 14, 17… | 2 | 3 | Node 2 |
3, 6, 9, 12, 15, 18… | 3 | 3 | Node 3 |
اگر یک برنامه عملیات اینسرت (INSERT) را با ترتیب زیر روی این کلاستر MySQL انجام دهد:
Node1, Node3, Node2, Node3, Node3, Node1, Node3 ..
کلیدهای اصلی ذخیره شده در جدول دیتابیس به این صورت خواهد بود:
1, 6, 8, 9, 12, 13, 15 ..
به طور ساده، در صورتی که از رپلیکیش مستر-مستر استفاده میکنید (چه رپلیکیشن MySQL چه گالرا کلاستر)، برنامه شما باید قابلیت تحمل کلیدهای اصلی نامتوالی را داشته باشد.
همخوانی یا سازگاری (Consistency) دادهها در کلاستر MySQL
گالرا کلاستر دارای یک مکانیزم کنترل جریان داده است که به نودهای یک کلاستر دیتابیس MySQL این امکان را میدهد تا در اعمال تغییرات از بقیه نودها عقب نیفتند؛ به این صورت که بقیه نودها سرعت اعمال تغییرات را کم میکنند تا نود کم سرعت از سینک خارج نشود. با این راهکار، احتمال لگ بین نودها به حداقل میرسد. به صورت پیشفرض Galera Cluster به نودهای کلاستر دیتابیس اجازه میدهد تا حداکثر ۱۶ تراکنش عقب بیفتند (که با متغیر gcs.fc_limit قابل تنظیم است). چنانچه بخواهید یک کوئری SELECT مهم انجام دهید که نیاز به بهروزترین دادهها داشته باشد، باید قبل از انجام کوئری نشست wsrep_sync_wait را ست کنید. در این صورت پایگاه داده قفل میشود تا جدیدترین تراکنشها را از کلاستر دریافت کند، سپس کوئری اجرا میشود تا جدیدترین اطلاعات را بازگرداند.
گالرا کلاستر دارای یک مکانیزم داخلی برای جلوگیری از ناسازگاری (inconsistency) دادهها است؛ به این صورت که اگر نودی به هر دلیلی نتواند writeset های کلاستر را اعمال کند، از گالرا کلاستر خارج میشود. این خروج با پیامهای خطای زیر همراه خواهد بود:
[ERROR] WSREP: Failed to apply trx 1 4 times [ERROR] WSREP: Node consistency compromized, aborting..
برای اینکه نود بتواند مجددا وارد کلاستر شود، باید دیتابیسِ نود ناسازگار مجددا سینک شود. این عمل میتواند به صورت دستی یا بازگردانی خودکار یک اسنپ شات (snapshot) انجام شود.
رپلیکیشن مستر-مستر خودِ MySQL اما سازگاری دادهها را اجبار نمیکند و این امکان وجود دارد که یکی از نودها از اعمال دادههای جدید عقب بیفتد. بررسی ناسازگاری پایگاه داده در این سناریو یا باید بصورت دستی انجام شود، یا با ابزارهای دیتابیس پرکونا (Percona) مانند pt-table-checksum و mysql-replication-check.
حل تعارض در دیتابیس
به طور ذاتی کلاسترهای دیتابیس مستر-مستر به بیش از یک نود یا عضو کلاستر این امکان را میدهند تا کوئریهای write را پردازش کنند. در رپلیکیشن داخلی MySQL مکانیزم خودکاری برای حل تعارضهای احتمالی بین نودهای کلاستر MySQL وجود ندارد. در صورت بروز تعارض، پروسه SQL از اعمال کوئریهای جدید خودداری کرده تا مشکل بصورت دستی (یا با اسکیپ کردن رویداد یا سینک مجدد دیتابیس) حل شود.
در طرف دیگر، گالرا کلاستر راهکار بهتری برای حل تعارض در رپلیکیشن دیتابیس دارد. با تنظیم متغیر wsrep_retry_autocommit میتوان کلاستر MySQL را مجبور کرد تا در صورت تعارض مجددا تراکنش را اعمال کند. این متغیر بصورت پیشفرض ۱ است و برای غیر فعال کردن آن میتوان مقدار آن را صفر گذاشت. این متغیر مخصوصا به درد برنامههایی میخورد که میخواهند کامیت خودکار (Autocommit) آنها با ددلاک (deadlock) مواجه نشود.
اجماع نودها و failover در کلاستر MySQL
گالرا کلاستر از پروتکل GCS (Group Communication System) برای اجماع کلاستر و بررسی دسترسیپذیری نودهای کلاستر MySQL استفاده میکند. در صورتی تایم اوت نود (پارامتر gmcast.peer_timeout که پیشفرض ۳ ثانیه است) پر شود، وضعیت نود به unhealthy تغییر کرده و بصورت خودکار از کلاستر اخراج میشود. یک نود گالرا در صورتی که در وضعیت synced قرار داشته باشد، healthy تلقی شده و به کوئریهای read و write پاسخ میدهد. این مکانیزم، راهکارهای healthcheck توسط لایههای بالاتر (مانند لود بالانسر load balancer) را بسیار راحت میکند.
در رپلیکیشن داخلی MySQL، نود مستر اهمیت چندانی به نودهای slave نمیدهد، نودهای slave هم به صورت مجزا و از طریق پروسه slave_IO_thread سینک بودن خود با نود مستر و دریافت رویدادهای باینری از آن را بررسی میکنند. در صورت fail شدن نود مستر، رپلیکیشن هم شکسته شده و نودهای slave هر ۶۰ ثانیه (مقدار پیشفرض برای slave_net_timeout) اقدام به اتصال مجدد به نود مستر میکنند. از دید load balancer در این راهکار، مکانیزم health check باید مقادیر زیر را بررسی کند:
Seconds_Behind_Master
Slave_IO_Running
Slave_SQL_Running
read_only variable
super_read_only variable (MySQL 5.7.8 and later)
از نظر failover، هر دو راهکار گالرا کلاستر و رپلیکیشن داخلی MySQL مشابه هستند. با توجه به ذات مستر-مستر رپلیکیشن، هر کدام از نودهای کلاستر دارای دادههای مشابه بوده و قابلیت پردازش کوئریهای read و write بصورت همزمان را دارند. بنابرین از نظر پایگاه داده failover موضوعیتی نداشته و فقط برنامهای که از کلاستر دیتابیس استفاده میکند باید توانایی نادیده گرفتن نودهای غیرعملیاتی را داشته باشد. به خاطر داشته باشید که رپلیکیشن MySQL آسنکرون بوده و احتمال وجود تاخیر در اعمال تغییرات در نودهای مختلف وجود دارد.
اضافه کردن نودهای جدید به کلاستر دیتابیس MySQL
در رپلیکیشن داخلی MySQL عملیات اضافه کردن نود جدید به کلاستر دیتابیس بصورت دستی انجام میشود. به این صورت که قبل از ایجاد رپلیکیشن جدید، باید یک پکاپ از نود مستر گرفته شده و به نود جدید انتقال داده شود. برای نودهای فعلی هم که رپلیکیشن آنها بر اساس expire_logs_days شکسته شده است، همین روند میتواند برای عضویت مجدد نود به کلاستر هم انجام شود. البته ابزارهای مختلفی، مانند تولکیت پرکونا (Percona Toolkit) برای کمک به این روند در رپلیکیشن MySQL وجود دارند. همچنین با استفاده از ClusterControl میتوان عملیات سینک مجدد نود کلاستر دیتابیس را با دو کلیک (از طریق کپی مستر فعلی یا بکاپ دیتابیس قبلی) انجام داد.
در گالرا کلاستر دو روش برای اضافه کردن نود جدید به کلاستر دیتابیس MySQL وجود دارد؛ روش اول: IST یا انتقال رویداد پلکانی (incremental state transfer)، روش دوم: SST یا انتقال بصورت اسنپ شات (state snapshot transfer). برای مواردی که فقط چند تراکنش از دست رفتهاند، روش IST اولویت دارد. روش SST مانند گرفتن یک بکاپ کامل (Full Backup) و انتقال آن عمل میکند و از نظر پردازشی نسبتا سنگین است. کلاستر گالرا بصورت خودکار و بر اساس وضعیت کلاستر بهترین روش را برای سینک دیتابیس انتخاب میکند. در مواردی که اضافه کردن نود جدید به کلاستر گالرا با خطا روبرو میشود، کافی است محتویات دایرکتوری datadir در MySQL را پاک کنید و مجددا سرویس MySQL را اجرا کنید. روند اضافه کردن نود جدید به گالرا کلاستر ساده است و افزایش مقیاس کلاستر دیتابیس و رفع مشکلات نودهای خراب را بسیار راحت میکند.
اتصال سفت در برای اتصال سست در کلاستر پایگاه داده
جفت شدن پایگاهدادهها در رپلیکیشن داخلی MySQL به اصطلاح سست (Loosely Coupled) است؛ به عبارت دیگر، میزان وابستگی بین نودهای مختلف کم است. رپلیکیشن MySQL با اتصالات کم سرعت و روی سختافزارها و سیستمعاملهای مختلف به راحتی کار میکند. همچنین از موتورهای ذخیرهسازی گوناگون مانند MyISAM، Aria، MEMORY و ARCHIVE پشتیبانی میکند. مجموعه این ویژگیها باعث شده تا کلاستر MySQL اصطلاحا سست باشد و رپلیکیشن مستر-مستر را در محیطهای متفاوت راحتتر کند.
در مقابل، اتصال نودها در کلاستر گالرا محکم (Tightly Coupled) است؛ به عبارت دیگر، وابستگی نودها در رپلیکیشن مستر-مستر به یکدیگر بالا بوده و سرعت رپلیکیشن به اندازه سرعت کندترین نود در کلاستر است. گالرا دارای مکانیزم کنترل جریان داده در رپلیکیشن است و به صورت خودکار سرعت رپلیکیشن بین نودهای مختلف را تنظیم میکند؛ این مکانیزم میتواند باعث افزایش یا کاهش سرعت در همه نودها شود. بنابرین توصیه میشود در کلاستر MySQL گالرا از منابع و زیرساخت مشابه (پردازشگر، رم، دیسک و سرعت شبکه و تاخیر) برای همه نودها استفاده شود.
نتیجهگیری
گالرا کلاستر در برابر رپلیکیشن مستر-مستر MySQL برتری محسوسی دارد. پشتیبانی از رپلیکیشن آسنکرون، سازگاری بالا و ویژگیهای پیشرفته مانند کنترل عضویت خودکار و slave های چند نخی (multi-threaded)، انتخاب گالرا کلاستر برای رپلیکیشن MySQL را بسیار راحت میکند. با توجه به موارد ذکر شده، به طور خلاصه موارد استفاده از هر کدام از رپلیکیشنهای MySQL به صورت زیر است:
در چه کاربردهایی از رپلیکیشن داخلی MySQL استفاده کنیم؟
- زمانی که منابع، زیرساخت و سرعت شبکه هر کدام از نودهای master متفاوت باشد (سناریو Loosely Coupled).
- زمانی که از قبل از رپلیکیشن داخلی MySQL استفاده میکنید و میخواهید برای افزونگی بیشتر (redundancy) یک نود جدید به کلاستر اضافه کنید.
- مواقعی که برنامه کاربردی شما قابلیت کنار آمدن با محدودیتهای گالرا کلاستر نداشته و امکان استفاده از یک لود بالانسر SQLی مانند ProxySQL یا MaxScale را ندارید.
محدودیتها و مواردی که گالرا کلاستر ساپورت نمیکند:
- جدولهای غیر از InnoDB.
- تراکنشهای XA.
- رپلیکیشن مبتنی بر Statement بین مسترها.
- وابستگی به استفاده مستقیم از قفل جدول (LOCK TABLES statement).
- لاگ عمومی دیتابیس و لاگ کوئریهای کند (Slow Query Log) بجای فایل در جدول ذخیره میشوند.
دلایلی که از گالرا کلاستر برای رپلیکیشن MySQL استفاده کنیم؟
- قابلیت اعمال ایمن کوئریهای write روی مسترهای مختلف.
- مدیریت خودکار سازگاری دادهها بین دیتابیسهای مختلف.
- اضافه و سینک کردن آسان نودهای جدید به کلاستر پایگاه داده.
- پاک کردن خودکار خطاها و ناسازگاریها.
- ویژگیهای HA (High Availability) پیشرفتهتر.
- پشتیبانی از کلاستر MariaDB.
دیتابیس ابری مدیریت شده پنکیک
در صورتی که برای اپلیکیشن یا برنامه خود نیاز به استفاده از یک پایگاه داده پرسرعت دارید، که علاوه بر امنیت بالا و پشتیبانی توسط متخصصین دیتابیس، روی دیتاسنتر مورد نظر خودتان میزبانی شود، میتوانید از طریق پرتال ثبت نام کنید و برای شارژ رایگان دیتابیس ابری پنکیک از طریق تیکت یا تلفن با ما تماس بگیرید. دیتابیسهای پنکیک به صورت کامل مدیریت شده هستند و در صورت نیاز توانایی کلاستر کردن دیتابیسهای خود برای دسترسی پذیری بالا (HA) را خواهید داشت.
خیلی اموزش خوبی بود من دیتابیسم کرش کرده بود تونستم حلش کنم مرسی