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

این مقاله در وبلاگ سایت shippable منتشر شده است و با توجه به گستردگی محبوبیت مانگودیبی در ایران، تصمیم گرفتیم تجربیات آنها را به سایر علاقهمندان منتقل کنیم تا در ابتدای کار، بهترین تصمیم را در انتخاب نوع دیتابیس بگیرند.
شروع کار و انتخاب مانگودیبی
شرکت ما (Shippable) در حدود پنج سال پیش به عنوان یک ابزار تجمیع پیوسته (CI) برای داکر شروع به کار کرد و امروزه تبدیل به یک بستر اتوماسیون توسعه نرمافزار بخصوص در حوزه عملیات توسعه (DevOps) شده است. امروزه بالای ۵۰ سرویس به همراه تعداد زیادی واسط برنامهنویسی (API) ارائه میکنیم و تعداد توسعهدهندگان و برنامهنویسان ما هم امروزه رشد بسیار زیادی داشته است.
از ابتدای کار، به خاطر اینکه دنبال برنامهنویسان همهفنحریف (Full Stack) بودیم و میخواستیم زبان توسعه فرانتاند و بکاند ما یکی شود، جاوا اسکریپت را به عنوان زبان اصلی انتخاب کردیم که سمت کاربر با انگولار کار کنیم و سمت بکاند و سرور هم با Node.JS کار شود. دنبال بانک اطلاعاتیای بودیم که هم با جاوااسکریپت بتوان به راحتی با آن کار کرد و هم انعطاف بالایی در مدل سازی دادهها داشته باشد. این بود که به سراغ مانگودیبی رفتیم .
همه چیز در ابتدای کار خوب و رضایت بخش بود تا اینکه ….
مشکلات آغاز میشوند
هر چه به سمت جلو حرکت میکردیم و قابلیتهای جدیدی را به مجموعه امکانات خود اضافه میکردیم، وقفههایی در سمت سرور رخ میداد که به نظر میرسید مشکل از مانگودیبی است :
- با وجود داشتن دو سرور اصلی و ثانویه برای ذخیره دادهها، خوشحال بودیم که به دسترسپذیری ۲۴*۷ رسیدهایم (۲۴ ساعت شبانه روز از هفت روز هفته). تا اینکه یک روز ناگهان، بانک اطلاعاتی ما دچار مشکل شد و وقتی تصمیم گرفتیم دادهها را بازیابی کنیم، به ازای هر سند، بیش از یک ثانیه زمان صرف میشد و این امر برای میلیونها سند، زمان زیادی بود. ابزارهای مدیریت دیتابیس هم گیر کار را به ما نشان نمیدادند. این بود که تصمیم گرفتیم یک سرور جدید با یک نسخه جدید مانگو بالا بیاوریم و یک بکاپ کامل از دیتابیس را روی آن بارگذاری کنیم. زمان بازیابی کل دیتابیس (و نه اصلاح و بازیابی تک تک اسناد) حدود ۱۵۰ میلی ثانیه بود که خوب، زمان مناسبی به نظر میرسید. هنوز هم نفهمیدیم که مانگو، دچار چه مشکلی شده بود و آیا در ادامه کار، باز هم به این مشکل برخواهیم خورد یا نه .
- حجم دادههای ما یواش یواش به ۴ ترابایت رسید و افتخار میکردیم که توانستهایم این حجم از دادهها را مدیریت کنیم. برای افزایش سرعت جستجو در این حجم عظیم داده، مجبور شدیم از ایندکسهای مختلف بر روی اسناد استفاده کنیم که این امر، حجم دیتابیس را بسیار بالا میبرد. نسخههای اولیه مانگودیبی، در تضمین یکتایی دادهها مشکل داشتند که باعث شد برای تضمین یکتایی برخی دادهها، ایندکسهای دیگری به دیتابیس خود اضافه کنیم. با افزایش حجم دیتابیس و بعد از انجام عملیات مختلف حذف و ویرایش، باید ایندکسها را از اول میساختیم که این امر باعث قفل شدن دیتابیس در بازههای زمانی مختلف میشد.
- یک روز نیاز به ریبوت سرور مانگو داشتیم. آنرا ریستارت کردیم و در کمال تعجب بالا آمدن آن ۴ ساعت طول کشید. این امر نارضایتی و سروصدای مشتریان را به دنبال داشت و بدتر از همه اینکه در حین بالا آمدن مانگو، هیچ نظارتی بر پشت صحنه کار نداشتیم تا بتوانیم در صورت نیاز به روند بالا آمدن آن، سرعت ببخشیم .
و بالاخره ضربه ناکاوت
مهمترین مزیت مانگو که اتفاقاً مهمترین عیب آن هم هست، ساختار منعطف جداول یا همان اسناد در آن است. طوری که هر سند (هر رکورد) در هر مجموعه (جدول) میتواند فیلدهای متفاوتی از بقیه اسناد داشته باشد و اِعمال قوانین سختگیرانه برای تعریف دادهها، در نهایت تاثیر چندانی در حفظ یکپارچگی دادهها ندارد.
این انعطاف، هر چند بسیار محبوب توسعهگران است اما بار بزرگی هم بر دوش آنها میگذارد. بگذارید مثالی عملی بزنیم. ما برای ذخیره اطلاعات مخازن کد گیتهاب، از فیلدهای زیر که به تدریج به رکوردها اضافه شدند، استفاده میکردیم :
field name | نام فیلد |
provider | 12/1/2012 |
repoOrg | 12/1/2012 |
repoName | 12/1/2012 |
isPrivate | 7/17/2014 |
hasTeams | 2/23/2016 |
همانطور که از جدول فوق مشخص است برای مخازن کد جدید، دو فیلد hasTeams و isPrivate موجود است اما دادههای قبلی، فاقد این اطلاعات هستند. بنابراین مجبور شدیم برای بررسی این موضوع، کد زیر را به برنامههای خود اضافه کنیم :
حال فرض کنید که ما بالای ۴۰ برنامه نویس داشتیم و تعداد زیادی سرویس که با اندک تغییری در ساختار دادهها، این بررسیها باید به کدها اضافه میشد که گاهاً در بخشی از کدها این شرط ها گذاشته نمیشد و برنامههای ما شروع کردند به تولید خطاهای ریز و درشت . از طرفی اگر میخواستیم این فیلدها را خودمان به تمام اسناد موجود اضافه کنیم باید تک تک اسناد بازیابی شده، تغییر میکردند و مجددا ذخیره میشدند که این امر سرعت و کارآیی دیتابیس را به حداقل میرساند. یک بار که مجبور شدیم این کار را انجام دهیم، مجبور شدیم بیش از ۴ ساعت، دیتابیس را از دسترس کاربران خارج کنیم.
تمام این مسایل باعث شد که به فکر جایگزینی ریشه این مسایل یعنی مانگودیبی با یک جایگزین مناسب و کارآمد باشیم .
پستگرس به داد ما رسید
بعد از آخرین خرابی مانگودیبی در یکسال پیش، تصمیم مهاجرت به پستگرس را گرفتیم که جزییات آنرا جداگانه در مقالهای توضیح خواهیم داد. اما پستگرس برای ما مزایای زیر را به همراه داشت :
- پستگرس مشابه سایر بانکهای اطلاعاتی رابطهای ساختار داده منظمی دارد و پیشاپیش میتوان ساختار جداول و ارتباطهات را تعریف کرد و در صورت نیاز، ستونهایی را کم یا زیاد کرد . افزودن یک ستون به آن، باعث افزوده شدن سریع آن به تمام دادهها میشود. این ساختار منظم باعث میشود بتوان یک معمار داده در سازمان به کار گرفت که مدیریت ساختارها و تغییرات از طریق او انجام گیرد.
- تغییر دیتابیس در پستگرس نیازمند قفل شدن کل دیتابیس نیست .
- پستگرس از دادههای جیسان که مورد نیاز ما بود هم پشتیبانی میکند و حتی آنها را موثرتر ذخیره میکند و میتوان برای ذخیره دادهها در قالب جیسان به راحتی توابع اعتبارسنج (بررسی کننده اعتبار و صحت دادهها) نوشت.
- حجم دیتابیس ما حدود نود درصد کاهش پیدا کرد!
- کارآیی و سرعت پستگرس در عملیاتی که از چندین جدول دادهها باید بازیابی میشدند بسیار چشمگیر بود که باعث افزایش رضایت مشتریان ما هم شد.
خوشحالیم که با مهاجرت به پستگرس، سردردهای دیتابیسی ما هم تمام شد و امروزه، معماری دادهای داریم که «همیشه کار میکند» …..
نکته : امیدوارم از این مطلب، استفاده کرده باشید اما در ذهن داشته باشید که اگر حجم دادههای شما زیاد نیست، ساختار دادههای شما خیلی تغییر نمی کند و یا ساختارهای بسیار تو در تو برای ذخیره دادهها دارید، شاید مانگو گزینه مناسبی باشد. این مقاله که یک مهاجرت معکوس از پستگرس به مانگو را شرح میدهد را هم میتوانید در این راستا مطالعه بفرمایید.