چگونه بر عملکرد MongoDB نظارت کنیم؟

نظارت یکی از بخش‌های کلیدی مدیریت پایگاه داده است، زیرا به شما اجازه می‌دهد عملکرد و وضعیت کلی پایگاه داده خود را درک کنید. با نظارت بر عملکرد پایگاه داده خود، می‌توانید ظرفیت فعلی آن را بهتر بشناسید، نحوه تغییر بار کاری آن را در طول زمان مشاهده کنید و زمانی که پایگاه داده به حد ظرفیت خود نزدیک شد، برای مقیاس‌پذیری برنامه‌ریزی کنید. همچنین این کار به شما کمک می‌کند تا مشکلات زیربنایی سخت‌افزاری یا رفتارهای غیرعادی مانند افزایش ناگهانی استفاده از پایگاه داده را شناسایی کنید. در نهایت، نظارت می‌تواند به تشخیص مشکلات مربوط به برنامه‌هایی که از پایگاه داده استفاده می‌کنند، مانند کوئری‌هایی که باعث گلوگاه می‌شوند، کمک کند.

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

برای دنبال کردن این آموزش به موارد زیر نیاز دارید:

توجه: آموزش‌های لینک شده برای تنظیم سرور، نصب MongoDB و ایمن‌سازی نصب MongoDB، مبتنی بر اوبونتو 20.04 هستند. این آموزش تمرکز بر MongoDB دارد و مستقل از سیستم‌عامل زیرین است. اصولاً این آموزش با هر نصب MongoDB که احراز هویت در آن فعال شده باشد، قابل اجرا است.

برای توضیح نحوه مانیتور کردن عملکرد MongoDB، ابتدا باید MongoDB shell را باز کنید و به نمونه MongoDB نصب شده محلی خود متصل شوید و یک کالکشن نمونه ایجاد کنید.

برای ایجاد کالکشن نمونه مورد استفاده در این آموزش، به عنوان کاربر مدیریتی خود به MongoDB shell متصل شوید. این آموزش مطابق با جزئیات آموزش امنیت MongoDB پارمین کلود است و فرض می‌کند نام کاربری مدیریتی شما AdminSammy است و پایگاه داده احراز هویت آن admin است. در صورت متفاوت بودن مشخصات خود، این موارد را در دستورات زیر تغییر دهید:

mongo --username AdminSammy --authenticationDatabase admin

رمز عبوری که در هنگام نصب تنظیم کرده‌اید را وارد کنید تا به shell دسترسی پیدا کنید. پس از وارد کردن رمز عبور، علامت > برای شما ظاهر می‌شود.

توجه: در اتصال تازه، MongoDB shell به صورت پیش‌فرض به پایگاه داده test متصل می‌شود. به صورت امن می‌توانید در این پایگاه داده آزمایش کنید.

همچنین می‌توانید به پایگاه داده دیگری برای اجرای دستورات آموزش تغییر کنید. برای سوئیچ به پایگاه داده دیگر، از دستور use به همراه نام پایگاه داده استفاده کنید:

use database_name

نظارت بر پایگاه داده زمانی کاربردی خواهد بود که با مجموعه داده‌ای بزرگ کار کنید، چرا که سیستم تنها با مقدار کمی داده نیازی به اسکن طولانی ندارد. برای نمایش ویژگی‌های نظارتی MongoDB، به دیتابیسی نیاز داریم که اجرای کوئری روی آن زمان‌بر باشد.

برای این منظور، مثال‌های این آموزش مرتبط با یک کالکشن نمونه به نام accounts هستند که حاوی تعداد زیادی سند است. هر سند نمایانگر یک حساب بانکی با موجودی به صورت تصادفی است. ساختار هر سند در این کالکشن به شکل زیر است:

{
"number": "1000-987321",
"currency": "USD",
"balance": 431233431
}

به جای درج دستی حجم بالا از داده‌ها، می‌توانید کد جاوااسکریپت زیر را اجرا کنید تا کالکشن accounts ایجاد شده و یک میلیون سند در آن وارد شود:

for (let i = 1; i <= 1000000; i++) {
    db.accounts.insertOne({
        number: "1000-" + i,
        currency: i > 500000 ? "USD" : "EUR",
        balance: Math.random() * 100000
    });
}

این کد یک حلقه for را یک میلیون بار پشت سر هم اجرا می‌کند. در هر بار تکرار، متد insertOne() روی کالکشن accounts اجرا شده و یک سند جدید وارد می‌شود. مقدار فیلد number به صورت 1000-1 برای اولین تکرار و به همین ترتیب برای آخرین تکرار 1000-1000000 خواهد بود.

واحد پول برای حساب‌هایی که شماره آن‌ها بالاتر از 500000 است به صورت USD و برای شماره‌های پایین‌تر به شکل EUR تنظیم شده است. فیلد balance به وسیله تابع Math.random() مقداری بین 0 تا 1 گرفته و در 100000 ضرب می‌شود تا مقدارهای بزرگ‌تری تولید شود.

توجه: اجرای این حلقه ممکن است مدت زمان زیادی، حتی بیش از ۱۰ دقیقه طول بکشد. می‌توانید بدون نگرانی منتظر بمانید تا عملیات به پایان برسد.

خروجی عملیات، پیام موفقیت و ObjectId سند آخر وارد شده را به شما نمایش می‌دهد.

برای اطمینان از درج صحیح اسناد، می‌توانید دستور count() را بدون آرگومان اجرا کنید تا تعداد اسناد موجود در کالکشن مشاهده شود:

db.accounts.count()

در این مرحله، شما لیستی از اسناد نمونه را با موفقیت ایجاد کردید که در ادامه آموزش برای شرح ابزارهای نظارتی MongoDB از آن‌ها استفاده می‌شود. در مرحله بعد، نحوه مشاهده آمار اولیه سرور را می‌آموزید.

MongoDB به صورت خودکار آمار مفیدی درباره عملکرد ثبت می‌کند و بررسی مرتب آن‌ها، روشی پایه برای نظارت بر پایگاه داده است. توجه داشته باشید که این آمارها اطلاعات لحظه‌ای یا real-time ارائه نمی‌دهند، اما در تعیین عملکرد کلی و تشخیص مشکلات احتمالی مفید هستند.

هشدار: دستورات نظارتی MongoDB که در این آموزش آمده‌اند، اطلاعات حساسی درباره پایگاه داده و عملکرد آن بازمی‌گردانند. به همین دلیل، اجرای بعضی از این دستورات نیازمند سطوح دسترسی بالاتر است.

به طور مشخص، متد serverStatus() و دستورات mongostat و mongotop به نقش clusterMonitor نیاز دارند. همچنین متد setProfilingLevel() به نقش dbAdmin نیاز دارد.

اگر آموزش ایمن‌سازی MongoDB پارمین کلود را دنبال کرده‌اید و به عنوان کاربر مدیریتی متصل شده‌اید، برای اجرای مثال‌های این آموزش، لازم است این نقش‌ها را به کاربر خود اضافه کنید.

ابتدا به پایگاه داده احراز هویت کاربر خود متصل شوید (در نمونه پایین پایگاه داده احراز هویت admin است):

use admin

سپس دستور grantRolesToUser() را اجرا کنید تا نقش‌های clusterMonitor و dbAdmin به کاربر داده شود؛ فرض شده که کالکشن accounts در پایگاه داده test است:

db.grantRolesToUser("AdminSammy", [
  { role: "clusterMonitor", db: "admin" },
  { role: "dbAdmin", db: "test" }
]);

توجه داشته باشید که در محیط‌های تولید، بهتر است کاربران با نقش‌های مخصوص به کاربری خاص ساخته شوند تا از گستردگی غیرضروری دسترسی‌ها جلوگیری شود. مثلاً یک کاربر مخصوص مانیتورینگ بسازید که فقط دسترسی‌های لازم را داشته باشد.

مثال ساخت کاربری به نام MonitorSammy با دسترسی‌های لازم به صورت زیر است (شامل نقش readWriteAnyDatabase برای امکان خواندن و نوشتن در تمام پایگاه داده‌ها):

db.createUser({
  user: "MonitorSammy",
  pwd: "your_password_here",
  roles: [
    { role: "clusterMonitor", db: "admin" },
    { role: "dbAdminAnyDatabase", db: "admin" },
    { role: "readWriteAnyDatabase", db: "admin" }
  ]
});

پس از افزودن نقش‌ها یا ساخت کاربر مناسب، به پایگاه داده‌ای که کالکشن accounts در آن است برگردید:

use test

ابتدا آمار کلی پایگاه داده را با دستور stats() بررسی کنید:

db.stats(1024*1024)

آرگومان این متد، عامل مقیاس است که در اینجا مقدار مگابایت (بایت تقسیم بر 1٬۰۴۸٬۵۷۶) را مشخص می‌کند. در صورت حذف، تمام مقادیر به بایت نشان داده می‌شوند.

خروجی این دستور خلاصه آمار مهمی درباره پایگاه داده فعلی را بازمی‌گرداند که شامل موارد زیر می‌تواند باشد:

  • تعداد کل اسناد، حجم داده‌ها، تعداد ایندکس‌ها، فضای استفاده شده و …

این اطلاعات دیدگاهی کلی از حجم داده‌های ذخیره شده در MongoDB ارائه می‌دهند، اما نمایشی از عملکرد و مشکلات سرور نیستند. برای همین، متد پرجزئیات‌تر serverStatus() ارائه شده است:

db.serverStatus()

خروجی این دستور بسیار طولانی است و اطلاعات متنوعی درباره سرور را نشان می‌دهد که در این آموزش به سه بخش اصلی توجه داریم.

اول از همه، بخش connections:

{
  connections: {
    current: عدد,
    available: عدد,
    totalCreated: عدد
  }
}

هر سرور پایگاه داده تعداد محدودی اتصال همزمان می‌تواند مدیریت کند. مقدار current تعداد کل اتصال‌های فعلی است و available تعداد اتصال‌های باقی‌مانده مجاز است. totalCreated مجموع اتصال‌هایی است که از زمان راه‌اندازی سرور ایجاد شده‌اند.

برنامه‌های معمولاً از اتصال‌های موجود مجدداً استفاده می‌کنند، لذا وقوع اتصال‌های زیاد (غیرمنتظره) می‌تواند نشانه‌ای از پیکربندی نادرست باشد.

اگر اتصال‌های زیاد به دلیل نوع کار بار منطقی است، می‌توانید از شاردینگ استفاده کنید تا بار بین چند نمونه MongoDB تقسیم شود.

دوم، بخش globalLock:

Output
        . . .
        "globalLock" : {
                "totalTime" : NumberLong(975312000),
                "currentQueue" : {
                        "total" : 0,
                        "readers" : 0,
                        "writers" : 0
                },
                "activeClients" : {
                        "total" : 0,
                        "readers" : 0,
                        "writers" : 0
                }
        },

MongoDB برای حفظ سازگاری داده‌ها هنگام انجام چند عملیات، از مکانیزم قفل استفاده می‌کند. روی سرورهای پرترافیک، ممکن است گاهی کوئری‌ها منتظر آزاد شدن قفل‌ها شوند که باعث کاهش کارایی می‌شود.

مقدار currentQueue.total نشان‌دهنده تعداد کوئری‌های منتظر برای قفل است. مقدار بالای این عدد نشان‌دهنده وجود گلوگاه‌های عملکردی است.

اغلب این مشکل ناشی از کوئری‌های طولانی‌مدت است که باعث نگه‌داشتن قفل می‌شوند. از این مشکلات می‌توان به استفاده نادرست از ایندکس‌ها یا طراحی بد کوئری اشاره کرد.

سوم، بخش opcounters:

Output
        "opcounters" : {
                "insert" : NumberLong(10000007),
                "query" : NumberLong(6),
                "update" : NumberLong(6),
                "delete" : NumberLong(0),
                "getmore" : NumberLong(0),
                "command" : NumberLong(1298)
        },

این بخش کمک می‌کند تا بفهمید سرور بیشتر در حال خواندن است یا نوشتن یا متعادل. مثلا پس از وارد کردن داده‌های آزمایشی تعداد عملیات insert نسبت به query بیشتر است.

سامانه‌های نوشتن سنگین می‌توانند با شاردینگ مقیاس‌پذیری یافته و سامانه‌های خواندن سنگین معمولاً از طریق replication بهره می‌برند.

این آمار به شما نمایی کلی از استفاده سرور می‌دهند اما اطلاعات لحظه‌ای نیستند. برای دریافت اطلاعات real-time ابزارهای mongostat و mongotop مفید هستند.

در حال حاضر، ابزارهای مرتبط با MongoDB برای مانیتورینگ real-time روی فعالیت دیتابیس به شرح زیر هستند:

  • mongostat: نمای کلی وضعیت فعلی MongoDB با به‌روزرسانی هر ثانیه
  • mongotop: نمایش زمانی که MongoDB صرف عملیات خواندن و نوشتن روی هر کالکشن می‌کند

هردوی این ابزارها در خط فرمان اجرا می‌شوند و برای استفاده باید از ترمینال سرور استفاده کنید (نه داخل MongoDB shell).

برای استفاده از mongostat، در حالی که اتصال MongoDB shell شما باز است، یک ترمینال دیگری باز کنید و دستور زیر را بزنید:

mongostat --username MonitorSammy --authenticationDatabase admin

در صورت فعال بودن احراز هویت، لازم است با کاربری که دسترسی لازم دارد احراز هویت کنید و رمز عبور را وارد نمایید.

مقدارهای متفاوت در هر ستون mongostat تعداد عملیات در هر ثانیه را نشان می‌دهد:

اگر مقدار 0 برای نوع کوئری دیده شود، یعنی در لحظه اجرای این ابزار، عملیات از آن نوع جاری نیست.

پس در ترمینال MongoDB shell، حلقه زیر را اجرا کنید تا 10000 سند جدید وارد شود و در ترمینال mongostat افزایش عملیات را ببینید:

for (let i = 1; i <= 10000; i++) {
    db.accounts.insertOne({
        number: "2000-" + i,
        currency: "USD",
        balance: Math.random() * 100000
    });
}

در زمان اجرای این حلقه، مقادیر ستون insert در خروجی mongostat افزایش می‌یابد و تعداد عملیات درج در ثانیه را نشان می‌دهد.

برای توقف اجرای mongostat در ترمینال مربوطه، از کلیدهای Ctrl + C استفاده کنید.

سپس می‌توانید ابزار mongotop را با دستور زیر اجرا کنید:

mongotop --username MonitorSammy --authenticationDatabase admin

خروجی mongotop لیستی از کالکشن‌های پایگاه داده است به همراه زمان صرف شده برای خواندن، نوشتن و کل زمان صرف شده در بازه زمانی مشخص شده. خروجی به صورت لحظه‌ای و هر ثانیه به‌روزرسانی می‌شود.

برای مشاهده فعالیت در mongotop، مجدداً چند حلقه درج (insert) داده را اجرا کنید و زمان صرف شده روی کالکشن accounts نمایش داده خواهد شد.

مانند mongostat، برای متوقف کردن mongotop کلید Ctrl + C را فشار دهید.

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

گلوگاه‌های عملکردی پایگاه داده می‌تواند دلایل متعددی داشته باشد. اگرچه مقیاس‌پذیری معمولاً راهکار است، ولی در بسیاری موارد مشکل از طراحی اسکیما یا کوئری‌هاست.

کوئری‌های پرهزینه معمولاً ناشی از استفاده نادرست از ایندکس‌ها یا طراحی اشتباه کوئری است. کوئری‌های طولانی اغلب به دلیل داده‌های آزمایشی کوچک یا تفاوت شرایط توسعه با محیط واقعی، در فرآیند توسعه نادیده گرفته می‌شوند.

با اجرای دستی و آزمایش کوئری‌ها می‌توانید منابع کند بودن آن‌ها را بیابید، اما روش دستی بسیار زمان‌بر است. خوشبختانه MongoDB ابزاری به نام database profiler دارد که این کار را به صورت خودکار انجام می‌دهد.

پروفایلر MongoDB می‌تواند کوئری‌هایی که شرایط خاصی دارند را ضبط و لاگ کند. مهم‌ترین شرط معمولاً مدت زمان اجرای کوئری است؛ کوئری‌هایی که طولانی اجرا شوند در پروفایلر به عنوان کوئری‌های مشکل‌ساز ثبت می‌شوند.

برای استفاده از پروفایلر ابتدا کوئری زیر را اجرا کنید که یکی از حساب‌های بانکی را می‌جوید:

db.accounts.findOne({number: "1000-7563"})

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

برای شناسایی کوئری‌های کند، پروفایلر را با دستور زیر فعال کنید:

db.setProfilingLevel(1, { slowms: 100 })

پارامتر اول یعنی سطح پروفایلینگ (0=غیرفعال، 1=لاگ کوئری‌های کند، 2=لاگ همه کوئری‌ها). پارامتر دوم یک شی دیتا با کلید slowms است که میزان میلی‌ثانیه تاخیر کوئری برای ثبت آن در پروفایلر را تعیین می‌کند (در مثال ۱۰۰ میلی‌ثانیه).

توجه: پروفایلر روی عملکرد تاثیر منفی می‌گذارد، چون مجبور است کوئری‌ها را تحلیل کند. باید با احتیاط و برای مدت کوتاه استفاده شود.

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

این دستور پس از فعال‌سازی پیغام موفقیت بازمی‌گرداند.

حالا پروفایلر فعال است و هر کوئری که بیش از ۱۰۰ میلی‌ثانیه زمان ببرد، در سیستم لاگ می‌شود.

چند کوئری مختلف تستی اجرا کنید:

db.accounts.count()

این کوئری سریع اجرا می‌شود و تعداد اسناد را بازمی‌گرداند.

db.accounts.find().limit(3)

نتایج ۳ سند اول را برمی‌گرداند، که باز هم سریع است.

db.accounts.findOne({number: "1000-7563"})

این کوئری زمان بیشتری می‌برد و باید در سیستم پروفایلر لاگ شود.

خروجی پروفایلر روی صفحه نمایش ظاهر نمی‌شود، بلکه در کالکشن ویژه‌ای به نام system.profile ذخیره می‌شود. این کالکشن یک کالکشن capped است که حداکثر ۱ مگابایت حجم دارد و همیشه فقط جدیدترین لاگ‌های‌ کوئری‌های کند را نگه می‌دارد.

برای مشاهده کوئری‌های لاگ شده توسط پروفایلر، این کوئری را اجرا کنید:

db.system.profile.find().sort({ ts: -1 }).pretty()

خروجی لیست اسناد مربوط به کوئری‌های کند است که با زمان (ts) به ترتیب نزولی مرتب شده‌اند.

هر سند نماینده یک کوئری کند است و می‌توانید آن را فیلتر، مرتب یا تحلیل کنید.

مثال خروجی نشان می‌دهد که پایگاه داده باید تمام کالکشن را برای پیدا کردن سند اسکن کند که نشان‌دهنده نیاز به ایندکس است.

در این مثال، ایجاد ایندکس روی فیلد number می‌تواند به شدت سرعت این کوئری‌ها را بهبود دهد. در شرایط واقعی راهکارهای بهینه‌سازی متفاوت خواهند بود.

برای پایان دادن به جلسه پروفایلینگ، مقدار پروفایلینگ را به صفر برگردانید:

db.setProfilingLevel(0)

با این کار، پروفایلر غیرفعال شده و پایگاه داده به حالت عادی بر می‌گردد.

هرگاه شک داشتید کوئری‌های کند روی عملکرد دیتابیس تاثیر منفی دارند، می‌توانید با پروفایلر آن‌ها را شناسایی و سپس بهینه‌سازی کنید.

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

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

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

Click to rate this post!
[Total: 0 Average: 0]

نظرات کاربران

دیدگاهی بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *