چرا از مانگودیبی به پستگرس مهاجرت کردیم؟
این مقاله در وبلاگ سایت 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 موجود است اما دادههای قبلی، فاقد این اطلاعات هستند. بنابراین مجبور شدیم برای بررسی این موضوع، کد زیر را به برنامههای خود اضافه کنیم :
حال فرض کنید که ما بالای ۴۰ برنامه نویس داشتیم و تعداد زیادی سرویس که با اندک تغییری در ساختار دادهها، این بررسیها باید به کدها اضافه میشد که گاهاً در بخشی از کدها این شرط ها گذاشته نمیشد و برنامههای ما شروع کردند به تولید خطاهای ریز و درشت . از طرفی اگر میخواستیم این فیلدها را خودمان به تمام اسناد موجود اضافه کنیم باید تک تک اسناد بازیابی شده، تغییر میکردند و مجددا ذخیره میشدند که این امر سرعت و کارآیی دیتابیس را به حداقل میرساند. یک بار که مجبور شدیم این کار را انجام دهیم، مجبور شدیم بیش از ۴ ساعت، دیتابیس را از دسترس کاربران خارج کنیم.
تمام این مسایل باعث شد که به فکر جایگزینی ریشه این مسایل یعنی مانگودیبی با یک جایگزین مناسب و کارآمد باشیم .
پستگرس به داد ما رسید
بعد از آخرین خرابی مانگودیبی در یکسال پیش، تصمیم مهاجرت به پستگرس را گرفتیم که جزییات آنرا جداگانه در مقالهای توضیح خواهیم داد. اما پستگرس برای ما مزایای زیر را به همراه داشت :
- پستگرس مشابه سایر بانکهای اطلاعاتی رابطهای ساختار داده منظمی دارد و پیشاپیش میتوان ساختار جداول و ارتباطهات را تعریف کرد و در صورت نیاز، ستونهایی را کم یا زیاد کرد . افزودن یک ستون به آن، باعث افزوده شدن سریع آن به تمام دادهها میشود. این ساختار منظم باعث میشود بتوان یک معمار داده در سازمان به کار گرفت که مدیریت ساختارها و تغییرات از طریق او انجام گیرد.
- تغییر دیتابیس در پستگرس نیازمند قفل شدن کل دیتابیس نیست .
- پستگرس از دادههای جیسان که مورد نیاز ما بود هم پشتیبانی میکند و حتی آنها را موثرتر ذخیره میکند و میتوان برای ذخیره دادهها در قالب جیسان به راحتی توابع اعتبارسنج (بررسی کننده اعتبار و صحت دادهها) نوشت.
- حجم دیتابیس ما حدود نود درصد کاهش پیدا کرد!
- کارآیی و سرعت پستگرس در عملیاتی که از چندین جدول دادهها باید بازیابی میشدند بسیار چشمگیر بود که باعث افزایش رضایت مشتریان ما هم شد.
خوشحالیم که با مهاجرت به پستگرس، سردردهای دیتابیسی ما هم تمام شد و امروزه، معماری دادهای داریم که «همیشه کار میکند» …..
نکته : امیدوارم از این مطلب، استفاده کرده باشید اما در ذهن داشته باشید که اگر حجم دادههای شما زیاد نیست، ساختار دادههای شما خیلی تغییر نمی کند و یا ساختارهای بسیار تو در تو برای ذخیره دادهها دارید، شاید مانگو گزینه مناسبی باشد. این مقاله که یک مهاجرت معکوس از پستگرس به مانگو را شرح میدهد را هم میتوانید در این راستا مطالعه بفرمایید.
پستگرس جز خانواده rdbms هست با توجه به اینکه sql server بخوبی از json پشتیبنی میکند آیا میتونه جایگزین مناسبی برای اون باشه ( بجز بجث هزینه) ؟
ممنون از مطلب خوب تون
سلام. Sql Server هم گزینه بسیار خوبیه بخصوص اینکه با سرویسهای ابری مایکروسافت کاملا یکپارچه و هماهنگه و مجموعه کاملی از ابزار را در اختیار شما قرار می دهد. برای خودم اول از همه قیمت و هزینه تهیه لایسنس معتبر اون یک مساله مهم هست و دوم مجموعه کاملی که حول پستگرس شکل گرفته از دیتابیس رابطه ای تا سری زمانی ، گراف و جی آی اس و همچنین امکان جداول خارجی در پستگرس که می تونه برخی داده های جداول را از یک دیتابیس دیگه مثل کاساندرا بخونه .
کلی اشتباه از مسیر انتخاب مونگو تا نحوه برخورد با مشکلات در مونگو و حتی مهاجرت به RDBMS داشتند که بنده در همان سایت بهشون توضیح دادم. این مقاله واقعا جای بحث داره و درست نیست.
شاید هم حق با شما باشه و انتخاب این مقاله توسط بنده با توجه به اینکه حدود سال ۴ سال پیش، روی حجم بالای داده روی مانگو به مشکل برخوردم، ممکن است کمی با سوگیری منفی ذکر شده باشد اما هدف اصلی از طرح این مباحث ، بررسی تمامی جنبه های مختلف یک کار و لحاظ کردن موارد مورد نیاز قبل از برخورد به مشکل است.
از طرفی در پایین این مقاله هم آدرس یک تجربه معکوس یعنی مهاجرت از پستگرس به مانگو را هم ذکر کرده ام که تنها بر اساس یک مقاله و نظر، تصمیم گیری نکنیم.
هیچ دلیل برای خرابی پایگاه داده ذکر نشده است پس این مقاله نمیتواند معیاری برای انتخاب پایگاه داده باشد.
بحث خرابی دیتابیس نیست بحث سرباری است که به تیم فنی بابت ساختار منعطف پستگرس و افزایش حجم ایندکس ها و دیتابیس و نیز مشکلاتی که گاها دلیل خاصی هم برای آن پیدا نکرده اند.
البته این یک مورد عملی و واقعی بوده است و مطمئنا تیم فنی این شرکت بزرگ، فارغ از بحثهای عاطفی و احساسی، تصمیمی که به نظر آنها برای شرکت مفید بوده است گرفته اند و الان هم مشکلاتشان مرتفع شده است.
ممکن است تیم فنی شما توانایی استفاده از mongo را نداشته است. هرچند شخصاً کار با یک دیتابیس رابطه ای پایدار و قوی را به mongo ترجیح میدهم
همانطور که در ابتدای مقاله آمده است این نوشته تجربه ایست از تیم فنی سایت Shippable که فکر نمی کنم تیم فنی ضعیفی داشته باشند.
اولا ممکنه اصلا برای صورت مسئلهای که داشتند انتخاب بانک اطلاعاتی NoSQL کار درستی نبوده باشه و صرف رایگان بودن بانک اطلاعاتی که نمیشه اون رو برای هر نوع صورت مسئله انتخاب کرد.
نحوه طراحی بانکهای اطلاعاتی از قبیل مونگو که نوعی از بانک های اطلاعاتی NoSQL هست کاملا متفاوت با طراحی بانکهای اطلاعاتی رابطهای هست. یه نمونه اینکه در مونگو اتفاقا برعکس بانکهای اطلاعاتی رابطهای باید افزونگی دیتا داشته باشید تا بتونید به سرعت و پرفرمنس بالاتری دست پیدا کنید در صورتی که در SQLServer و در کل RDBMS ها کاملا برعکس این موضوع صدق می کنه. با صحبتهایی که در گزارش این شرکت نوشته شده احتمالا راه حال بهینه این بوده که می رفتند به سراغ بانکهای اطلاعاتی RDBMS
حجم مونگو برای زمانی که از سیستم فایل استفاده نشده باشه واقعا کم هست البته اگه فایل هم در بانک اطلاعاتی بخواهید ذخیره کنید امکانش وجود داره ولی پیشنهاد نمیشه چون سیستم فایل بر روی بانک اطلاعاتی حتی روی SQLServer هم برای ذخیره فایلهای زیاد Best Practice نیست و پیشنهاد میشه فایلها بر روی سرور و هارد در پوشهای ذخیره بشه تا روی بانک اطلاعاتی. شاید در شرکت shippable فایلها رو هم روی بانک اطلاعاتی ذخیره میکردند که اینقدر حجم دیتای زیادی داشتند.
انتخاب ایندکسها هم برای بانک اطلاعاتی خیلی مهم هست حتی روی SQLServer هم اگر شما انتخاب ایندکسهای درستی نداشته باشید باعث کند شدن و حجم بسیار زیاد بانک اطلاعاتی میشه.همه اینها در کنار نحوه کوئری گرفتن بهینه و استفاده بهینه از مونگو در کدنویسی سمت اپلیکیشن هم لازمه که رعایت بشه. مثلا برای اطلاعاتی که در اپلیکیشن قرار است زیاد به آن رجوع شود بهتر است از سیستم Caching یا انواع بانکهای اطلاعاتی مناسب از قبیل Redis در کنار MongoDB استفاده شود.
ضمنا مونگو مزایای بسیار زیاد دیگری هم دارد که اون رو برای بسیاری از پروژه ها ممتاز کرده و در نسخه های جدید آن هم بسیار عملکرد بهتری از قبل داشته.
حجم دیتابیستون که بعد از مهاجرت به پستگرس ، ۹۰ درصد کاهش پیدا کرد ، دقیقا چقدر شد .
اگه به ابتدای مقاله دقت کنید، مقاله متعلق به تجربیات شرکت خارجی Shippable هست و اطلاعی راجع به حجم داده ها در مقاله اصلی تا جایی که در خاطرم مونده نبود.