Data & Infrastructureপড়তে ১৩ মিনিট লাগবে

মেট্রিক্স মনিটরিং সিস্টেম ডিজাইন

লক্ষ লক্ষ টাইম-সিরিজ ডেটা সংগ্রহ, স্টোর, কোয়েরি এবং অ্যালার্ট করার ব্যবস্থা — ঠিক Datadog বা Prometheus-এর মতো
scope:বাস্তব সিস্টেমdifficulty:অ্যাডভান্সড

সমস্যাটি বোঝা

আধুনিক ডিস্ট্রিবিউটেড সিস্টেমগুলো থেকে ব্যাপক পরিমাণ মেট্রিক্স তৈরি হয় — যেমন CPU ব্যবহার, রিকোয়েস্ট ল্যাটেন্সি (দেরি), এরর রেট, কিউয়ের গভীরতা ইত্যাদি। একটি মেট্রিক্স মনিটরিং সিস্টেম এই সমস্ত ডেটা সংগ্রহ করে, সেগুলোকে টাইম-সিরিজ বা সময়ের ক্রমানুসারে সেভ করে, ইঞ্জিনিয়ারদের তা কোয়েরি ও ভিজ্যুয়ালাইজ করার সুবিধা দেয়, এবং কোনো সমস্যা হলে অ্যালার্ট বাজায়।

Datadog, Prometheus + Grafana, বা AWS CloudWatch-এর কথা চিন্তা করুন।

ফাংশনাল রিকয়ারমেন্টস:

  • মেট্রিক্স গ্রহণ করা: হাজার হাজার সার্ভিস থেকে মেট্রিক্স টানা (পুশ অথবা পুল মডেল ব্যবহার করে)।
  • টাইম-সিরিজ ডেটা স্টোর করা: হাই রাইট থ্রুপুট এবং দারুণ কম্প্রেশনের মাধ্যমে টাইম-সিরিজ ডেটা সেভ করা।
  • কোয়েরি এবং অ্যাগ্রিগেট করা: যেকোনো সময়ের ব্যাপ্তির ওপর মেট্রিক্স কোয়েরি করে বের করা (যেমন গড়, সমষ্টী, পার্সেন্টাইল)।
  • ড্যাশবোর্ডস: রিয়েল-টাইম এবং আগের মেট্রিক্সগুলো চোখের সামনে গ্রাফে দেখা।
  • অ্যালার্ট দেওয়া: নির্দিষ্ট থ্রেশহোল্ড এবং অ্যানোমালি (অস্বাভাবিকতা) ডিটেকশনের ওপর ভিত্তি করে অ্যালার্ট পাঠানো এবং নির্দিষ্ট জায়গায় মেসেজ পাঠানো (যেমন PagerDuty, Slack, ইমেইল)।

নন-ফাংশনাল রিকয়ারমেন্টস:

  • রাইট থ্রুপুট: প্রতি সেকেন্ডে ১০ মিলিয়ন ডেটা পয়েন্ট ঢোকা।
  • কোয়েরি ল্যাটেন্সি: কয়েক ঘণ্টা বা কয়েক দিনের ড্যাশবোর্ড কোয়েরির জন্য ১ সেকেন্ডের কম সময় নেওয়া।
  • অ্যাভেইলেবিলিটি: ৯৯.৯% আপটাইম — যখন সবচেয়ে বেশি দরকার, তখন অ্যালার্টিং যেন কোনোভাবেই ডাউন না থাকে।
  • রিটেনশন (ডেটা ধরে রাখা): স্বয়ংক্রিয় ডাউনস্যাম্পলিং করে ১ বা তার বেশি বছরের পুরোনো ডেটা ধরে রাখা।
ধারণা: সংগ্রহ → স্টোর → কোয়েরি → অ্যালার্ট

প্রাথমিক একটা হিসাব-নিকাশ

চলুন সিস্টেমটার সাইজ মেপে দেখি:

  • ১০,০০০ সার্ভিস, প্রতিটি থেকে প্রতি ১০ সেকেন্ডে ~৫০০ করে মেট্রিক বেরোচ্ছে।
  • রাইট রেট: ১০,০০০ × ৫০০ / ১০ = ৫ লাখ রাইটস/সেকেন্ড (সাধারণ অবস্থায়)। পিক টাইমে প্রায় ২০ লাখ/সেকেন্ড।
  • প্রতিটি ডেটা পয়েন্টের সাইজ: মেট্রিকের নাম + ট্যাগস + টাইমস্ট্যাম্প + ভ্যালু মিলে র-ডেটা প্রায় ১০০ বাইট, কম্প্রেস করলে ~১৬ বাইট (Gorilla কম্প্রেশনে ১২ গুণ পর্যন্ত ছোট করা যায়)।
  • প্রতিদিনের র-ডেটা: ৫ লাখ × ৮৬,৪০০ × ১৬ বাইট = প্রতিদিন ~৬৯০ গিগাবাইট কম্প্রেসড ডেটা।
  • ১ বছরের রিটেনশন: ৬৯০ গিগাবাইট × ৩৬৫ = ~২৫০ টেরাবাইট কম্প্রেসড ডেটা। ডেটা রোলআপ করার পর: র-ডেটা (২ সপ্তাহ) + ১-মিনিটের ডেটা (৩ মাস) + ১-ঘণ্টার ডেটা (১ বছর) মিলে মোট ~১৫ পেটাবাইট র-ডেটার সমতুল্য, যা স্টোর করতে ~৫০ টেরাবাইট লাগবে
  • কোয়েরি ফ্যানআউট: একটি ড্যাশবোর্ড প্যানেল হয়তো একাধিক পার্টিশনে ছড়িয়ে থাকা ১০০-র বেশি টাইম-সিরিজ কোয়েরি করে বসতে পারে।

সবচেয়ে বড় চ্যালেঞ্জ হলো একসাথে এত রাইট সামলানো, পাশাপাশি এত বিশাল সময়ের স্কোপে কোয়েরিগুলো সুপারফাস্ট রাখা।

টাইম-সিরিজ ডেটা মডেল

প্রতিটি ডেটা পয়েন্ট দেখতে এমন হয়:

{
  "metric_name": "http.request.latency_ms",
  "tags": {
    "host": "web-server-42",
    "service": "api-gateway",
    "region": "us-east-1",
    "endpoint": "/api/v1/users"
  },
  "timestamp": 1709251200,
  "value": 42.5
}

একটি ইউনিক টাইম-সিরিজ (মেট্রিকের নাম + সর্ট করা ট্যাগ) দিয়ে সংজ্ঞায়িত করা হয়। একই সিরিজের সব ডেটা পয়েন্ট এক জায়গায় রাখা হয় যাতে তাদের খুব ভালোভাবে কম্প্রেস করা যায়।

কম্প্রেশন (Gorilla পেপার অনুযায়ী):

  • টাইমস্ট্যাম্প: ডেল্টা-অফ-ডেল্টা এনকোডিং। যদি প্রতি ১০ সেকেন্ড পরপর টাইমস্ট্যাম্প আসে, তবে ডেল্টা সবসময়ই ~১০ হবে। তখন ডেল্টা-অফ-ডেল্টা হবে ~০, যাকে স্টোর করতে মাত্র ১ বিট লাগে!
  • ভ্যালু: XOR এনকোডিং। পরপর পাওয়া ফ্লোট (দশমিক) ভ্যালুগুলো প্রায়ই একই রকম থাকে। দুটি কাছাকাছি IEEE ৭৫৪ ফ্লোটের XOR করলে শুরুতে অনেকগুলো শূন্য (০) আসে, যা খুব সুন্দর কম্প্রেস হয়।
  • ফলাফল: প্রতিটি ডেটা পয়েন্টের জন্য ~১.৩৭ বাইট করে লাগে (১৬ বাইট পয়েন্ট থেকে এক লাফে ১২ গুণ কম্প্রেশন)।

ডেটাগুলোকে ব্লক-এ (সাধারণত ২ ঘণ্টার চাঙ্ক) ভাগ করে স্টোর করা হয়। একবার ফ্লাশ হয়ে গেলে একেকটা ব্লক অপরিবর্তনযোগ্য (immutable) হয়ে যায়, যার ফলে এগুলোকে একসাথে কম্প্যাক্ট করা বা আলাদা স্টোরেজ টিয়ারে সরানো খুব সহজ হয়।

টাইম-সিরিজ স্টোরেজ: কম্প্রেশন এবং পার্টিশনিং
Click chart to zoom
ইনজেস্ট বা ঢোকার পাইপলাইন: এজেন্টরা মেট্রিক্সগুলোকে কালেক্টর এবং কাফকার সাহায্যে রাইটার পুলে পুশ করে, যেখানে পিওডিক কমপ্যাকশন হওয়ার আগে সেগুলো WAL এবং ইন-মেমোরি ব্লকে গোছানো হয়

কোয়েরি ইঞ্জিন এবং অ্যালার্টিং

কোয়েরি ইঞ্জিনটি PromQL-স্টাইল-এর একটি ভাষা সাপোর্ট করে যাতে খুব সহজে টাইম-সিরিজ কোয়েরি করা যায়:

# গত এক ঘণ্টায় সার্ভিস অনুযায়ী গড় রিকোয়েস্ট ল্যাটেন্সি
avg by (service) (
  rate(http_request_latency_ms[5m])
)

# ৯৯তম পার্সেন্টাইলের ল্যাটেন্সি
histogram_quantile(0.99, rate(http_request_duration_bucket[5m]))

লং-রেঞ্জ বা বড় পরিসরের কোয়েরির জন্য ডাউনস্যাম্পলিং (Downsampling) করা খুবই ইম্পর্টেন্ট:

  • র-ডেটা (Raw data) (১০-সেকেন্ডের রেজোলিউশন) — ২ সপ্তাহ পর্যন্ত রাখা হয়।
  • ১-মিনিটের রোলআপ (গড়, সর্বনিম্ন, সর্বোচ্চ, মোট সংখ্যা) — ৩ মাস পর্যন্ত রাখা হয়।
  • ৫-মিনিটের রোলআপ — ৬ মাস পর্যন্ত রাখা হয়।
  • ১-ঘণ্টার রোলআপ — ১ বছর বা তার বেশি সময় ধরে রাখা হয়।

"গত ৬ মাসের CPU" দেখতে চেয়ে যখন ড্যাশবোর্ড কোয়েরি করে, তখন সে ১-ঘণ্টার রোলআপ ডেটা পড়ে। এতে তাকে দেড় কোটির বদলে মাত্র ~৪,৩৮০ টি পয়েন্ট পড়তে হয়।

অ্যালার্ট ইভাল্যুয়েশন (Alert Evaluation):

  • একটি অ্যালার্ট ইভাল্যুয়েশন ইঞ্জিন একটা নির্দিষ্ট সময় পরপর (প্রতি ১৫-৬০ সেকেন্ডে) কোয়েরি রান করায়।
  • থ্রেশহোল্ড অ্যালার্টস: avg(cpu_usage) > 90% for 5 minutes
  • অ্যানোমালি ডিটেকশন: স্ট্যাটিস্টিক্যাল মডেল ব্যবহার করে স্বাভাবিকের তুলনায় কোনোকিছু অস্বাভাবিক হচ্ছে কিনা তা দেখে অ্যালার্ট।
  • এরপর এগুলোকে একটি নোটিফিকেশন পাইপলাইনের ভেতর দিয়ে পাঠানো হয়: ডিডুপ্লিকেশন (ডাবল মেসেজ বাদ দেওয়া) → গ্রুপিং → থ্রটলিং → PagerDuty/Slack/Email-এ পাঠানো।
  • একটি নির্দিষ্ট সিডিউল দিয়ে ডিউটি সেট করা থাকে যেন পেজ (অ্যালার্ট কল) সঠিক মানুষের কাছে যায়।
কোয়েরি এবং অ্যালার্ট পাইপলাইন

স্টোরেজ টিয়ার বা স্তর

সব ডেটার জন্যই সমান পারফরম্যান্স দরকার নেই। খরচের কথা মাথায় রেখে স্টোরেজগুলোকে বিভিন্ন স্তরে ভাগ করা হয়:

  • হট টিয়ার (নতুন ডেটা, < ২ সপ্তাহ): ফাস্ট SSD এবং ইন-মেমোরি ক্যাশ ব্যবহার করা হয়। এটি রিয়েল-টাইম ড্যাশবোর্ড এবং অ্যালার্ট কোয়েরির জন্য। কোয়েরিগুলোর বেশিরভাগই এখানেই যায়।
  • ওয়ার্ম টিয়ার (কয়েক সপ্তাহ থেকে মাস): এটি মূলত HDD-ভিত্তিক স্টোরেজ বা কম দামি SSD। এটি পুরোনো ড্যাশবোর্ড দেখার জন্য ব্যবহার করা হয়। ডেটাগুলো ফাস্ট কোয়েরির জন্য আগেই রোল-আপ করে রাখা হয়।
  • কোল্ড টিয়ার (কয়েক মাস থেকে বছর+): এখানে সস্তা অবজেক্ট স্টোরেজ (S3/GCS) ব্যবহার করা হয়। এটি বিভিন্ন অডিট বা বিরল দীর্ঘমেয়াদী অনুসন্ধানের জন্য রাখা হয়। কোয়েরি তুলনামূলক ধীর হলেও এই সব কাজে তা মানিয়ে নেওয়া যায়।

কমপ্যাকশন (Compaction) প্রক্রিয়ার মাধ্যমে অনেকগুলি ছোট ২-ঘণ্টার ব্লককে বড় ব্লকে মেশানো হয়। এতে করে ফাইল সংখ্যা কমে, কোয়েরি করা আরও সহজ ও দ্রুত হয়, এবং আরও স্ট্রং কম্প্রেশন দেওয়া যায়। এটি ডাটাবেসের LSM-ট্রির কমপ্যাকশনের মতোই।

ডেটার বয়সের ওপর নির্ভর করে এটি অটোমেটিকভাবে একটি ব্যাকগ্রাউন্ড সার্ভিস দিয়ে হট → ওয়ার্ম → কোল্ড স্তরে চলে যায়।

সম্পূর্ণ আর্কিটেকচার
Note: ইন্টারভিউ টিপস: পুশ বনাম পুল মডেল। Prometheus একটি পুল (pull) মডেল ব্যবহার করে — সে নির্দিষ্ট শিডিউলে সার্ভিস এন্ডপয়েন্টগুলো থেকে মেট্রিক্স টেনে নিয়ে আসে। এটি Prometheus-কে নিজেদের মতো ডেটা কালেকশন রেট নিয়ন্ত্রণ করার স্বাধীনতা দেয় এবং কোনো সার্ভিস অফলাইনে গেলে সহজেই বুঝতে পারে (স্ক্র্যাপিং ফেইল করে)। অন্যদিকে Datadog পুশ (push) মডেল ব্যবহার করে — প্রতিটি হোস্টে থাকা এজেন্টরা একটা কালেক্টরে মেট্রিক্স পুশ করে। যেখানে প্রতিনিয়ত সার্ভিস আসে আর যায় (যেমন কন্টেইনার, সার্ভারলেস অ্যার্কিটেকচার), সেখানে ডেটা পাঠানোর জন্য পুশ মডেল বেশ ভালো। অনেক প্রোডাকশন সিস্টেমে দুটোর মিশ্রণ দেখা যায়: এজেন্টরা লোকাল কালেক্টরের কাছে পুশ করে এবং একটি সেন্ট্রাল সিস্টেম কালেক্টরগুলো থেকে পুল করে।

Key Metrics

ডেটা ইনজেশন রেট
কাফকা বাফারের সাথে রাইটার শার্ডিং করে রাখা
৫ লাখ–১ কোটি পয়েন্ট/সেকেন্ড —
কোয়েরি ল্যাটেন্সি (ড্যাশবোর্ড)
মেট্রিকস+ট্যাগ দ্বারা ইনডেক্স করা, প্রি-রোলআপ ডেটা
১০০ মি.সে.–১ সেকেন্ড —
প্রতি বছরের স্টোরেজ
Gorilla কম্প্রেশন + বিভিন্ন স্তরে রোলআপ
~৫০ টেরাবাইট —
কম্প্রেশন রেশিও
ডেল্টা-অফ-ডেল্টা + XOR (Gorilla পেপার)
~১২ গুণ —

ছোট কুইজ

মেট্রিকের টাইমস্ট্যাম্পগুলোর জন্য ডেল্টা-অফ-ডেল্টা (১০-১০=০) এনকোডিং কেন এত কার্যকরী?

পড়া চালিয়ে যান