با Redis Sentinel دیگه نگران کرش کردن Master نباش!

Redis Sentinel
Redis Sentinel

مقدمه

اگر تا حالا با Redis کار کردید، احتمالاً می‌دونید که این دیتابیس سریع و دوست‌داشتنی چقدر توی کش کردن و مدیریت داده‌های موقتی محبوبه. اما چالش از اونجایی شروع می‌شه که قراره High Availability رو پیاده کنیم. خب، بیاید ببینیم چه گزینه‌هایی داریم و چرا Redis Sentinel یه انتخاب هوشمندانه‌ست!


انواع مدل‌های پیاده‌سازی Redis:

۱. مدل Standalone (تک‌نفره! 🤷‍♂️)

  • یه نمونه Redis داریم و همه درخواست‌ها رو اون پاسخ می‌ده.
  • خب، ولی اگه این کرش کنه، فاتحه!

۲. مدل Master-Slave (سلطنت دو نفره! 👑)

  • یه Master داریم که می‌نویسه، Slaveها فقط می‌خونن.
  • اگه Master بمیره، دستی باید جابه‌جا کنیم که خیلی سخته!

۳. مدل Cluster Mode (جمع باحال! 🎉)

  • داده‌ها رو Sharding می‌کنه و تو چندتا نود پخش می‌شه.
  • اما مدیریت و راه‌اندازی یه کم دردسر داره.

۴. مدل Sentinel (ناظر وفادار! 👀)

  • یه سیستم نظارت خودکار که Master رو پایش می‌کنه و اگه مرد، سریعاً یه Slave رو جایگزین می‌کنه.
  • نیازی نیست دستی مداخله کنیم، و خب، فوق‌العاده برای High Availability!



سوال بزرگ: Redis Sentinel چگونه کار می‌کند؟

جناب Redis Sentinel از سه مؤلفه اصلی تشکیل شده است:

  1. ‏Monitoring: به‌صورت مداوم Master و Replicaها را بررسی می‌کند تا اطمینان حاصل شود که سالم هستند.
  2. Notification: اگر مشکل یا خرابی‌ای تشخیص دهد، می‌تواند به ادمین اطلاع دهد.
  3. Automatic Failover: اگر Master از دسترس خارج شود، یکی از Replicaها را به Master تبدیل کرده و سایر Replicaها را به آن متصل می‌کند.

مکانیزم Failover در Sentinel به این شکل است:

  • ‏Sentinelها به‌صورت quorum (یکم پایینتر توضیح میدم چیه) تصمیم می‌گیرند که Master خراب شده است.
  • پس از تایید خرابی، یک Sentinel به عنوان Leader انتخاب می‌شود.
  • ‏Leader یک Replica را به عنوان Master جدید معرفی کرده و سایر نودها را مجدداً پیکربندی می‌کند.
  • کلاینت‌ها با استفاده از Sentinelها، اطلاعات به‌روزرسانی‌شده Master جدید را دریافت می‌کنند.

این یعنی نیازی به مداخله دستی نیست و همه‌چیز خودکار مدیریت می‌شود!


حالا Quorum چیست و چرا مهم است؟

در سیستم Sentinel، چندین نود وظیفه بررسی Master را دارند. برای اینکه Failover اتفاق بیافتد، حداقل n/2+1 از Sentinelها باید تأیید کنند که Master واقعاً از کار افتاده است. این مکانیزم که Quorum نام دارد، جلوی Failoverهای اشتباه را می‌گیرد و باعث ثبات در سیستم می‌شود.


‏مزایای Redis Sentinel چیه؟

‏✅ Failover اتوماتیک: اگه Master بمیره، خودش یه Slave رو ارتقا می‌ده.

‏✅ Load Balancing برای Read: کلاینت می‌تونه به چند تا Replica متصل بشه و فشار کم بشه.

‏✅ Monitoring & Notification: اگه Redis یه مشکلی پیدا کنه، بهت اطلاع می‌ده.

بدون نیاز به کلاینت خاص: همون کلاینت Redis معمولی کار می‌کنه.

‏✅ Self-healing: به‌صورت خودکار شبکه رو تنظیم می‌کنه.


‏مشکلاتی که Sentinel حل می‌کنه

‏🚀 دستکاری دستی در مواقع خرابی: دیگه لازم نیست خودمون نگران Failover باشیم.

‏🛑 Single Point of Failure: بدون Sentinel اگه Master بمیره، کلی مشکل داریم.

📈 افزایش عملکرد: درخواست‌های Read بین Replicaها پخش می‌شه.

⚠️ کاهش ریسک Data Loss: به دلیل مدیریت خودکار Failover.



انتخاب Master توی Redis Sentinel، یه جور انتخابات هوشمندانه! 🎭

وقتی Master بی‌خبر غیبش می‌زنه، Sentinelها دور هم جمع می‌شن و یه تصمیم مهم می‌گیرن: کی بشه Master بعدی؟! 🤔

۱. تشخیص مرگ Master 😵

‏Sentinelها همیشه حواسشون به Master هست. هر چند ثانیه یه پینگ می‌فرستن و منتظر جواب می‌شن. اگه چندتا Sentinel ببینن که دیگه Master جواب نمی‌ده، می‌گن: «خب، به‌نظر می‌رسه که کارش تمومه!». 😬 اما این کافی نیست!

  • باید حداقل نصف Sentinelها + ۱ تا، نظرشون این باشه که Master واقعاً غیبش زده (به این می‌گن Quorum).
  • اگه Quorum تأیید کنه که Master از دنیا رفته، می‌ره توی ODOWN (Objectively Down) و پروژه انتخاب جایگزین شروع می‌شه.

۲. انتخاب یه Sentinel به عنوان رئیس جمهور! 🤴

وقتی Master از دسترس خارج می‌شه، Sentinelها رأی‌گیری می‌کنن تا یکی‌شون نقش لیدر رو بگیره و هدایت Failover رو به دست بگیره.

  • این رأی‌گیری یه جورایی مثل انتخابات کلاس درسه! هر Sentinel تلاش می‌کنه رأی بگیره.
  • هرکی رأی اکثریت رو بیاره، می‌شه Leader و بقیه ازش تبعیت می‌کنن. 😎
  • اگه هیچ‌کس رأی نیاره؟ رأی‌گیری دوباره انجام می‌شه تا یکی بالاخره انتخاب بشه.

۳. تعیین جانشین (Replica جدید برای Master شدن!) 👑

خب، حالا که رئیس انتخاب شد، باید یه Master جدید پیدا کنه. ولی هر Replica‌ای مناسب این کار نیست! Sentinel چند تا چیزو چک می‌کنه:

  • آخرین داده‌ها: کدوم Replica به‌روزتره؟
  • در دسترس بودن: کدومش جواب می‌ده؟
  • اولویت (priority): اگه تو تنظیمات یه Replica بالاتر باشه، شانسش بیشتره.
  • ‏Latency: هرچی سریع‌تر باشه، بهتره.

بعد از کلی بررسی، یه Replica انتخاب می‌شه و با اجرای SLAVEOF NO ONE تبدیل به Master جدید می‌شه. 🎉

۴. اعلام رسمی تغییرات! 📢

حالا که Master جدید انتخاب شد، وقتشه که به کلاینت‌ها و سایر نودها بگه: «هی بچه‌ها! این رئیس جدیدتونه!»

  • ‏Sentinel اطلاعات رو آپدیت می‌کنه.
  • ‏Replicaهای دیگه به Master جدید متصل می‌شن.
  • کلاینت‌ها هم بعد از یه مدت کوتاه خودشون به Master جدید وصل می‌شن.

۵. نظارت مداوم روی Master جدید 👀

‏Sentinelها همچنان کارشون رو ادامه می‌دن و اگه Master جدید هم یه وقت غیبش زد، دوباره همین پروسه رو انجام می‌دن.

جمع‌بندی Failover توی Redis Sentinel

‏✅ Sentinelها دائماً Master رو چک می‌کنن.

اگه Master بمیره، رأی‌گیری می‌شه و یه Sentinel لیدر می‌شه.

لیدر یه Replica رو انتخاب و به Master جدید تبدیل می‌کنه.

کلاینت‌ها و Replicaهای دیگه آپدیت می‌شن.

✅ ‏Sentinel همچنان روی Master جدید نظارت داره.

و اینجوری Redis Sentinel بدون نیاز به دخالت دستی، یه سیستم همیشه در دسترس رو مدیریت می‌کنه! 😎🚀


اتصال کلاینت به Redis Sentinel

نمونه کد در Python

import redis
sentinels = [("redis-sentinel-0", 26379), ("redis-sentinel-1", 26379), ("redis-sentinel-2", 26379)]
rs = redis.sentinel.Sentinel(sentinels, socket_timeout=0.1)
master = rs.master_for("mymaster", socket_timeout=0.1)
slave = rs.slave_for("mymaster", socket_timeout=0.1)
master.set("key", "value")
print(slave.get("key"))

‏نمونه کد در Golang

package main
import (
    "fmt"
    "github.com/go-redis/redis/v8"
    "context"
)

var ctx = context.Background()
func main() {
    sentinel := redis.NewFailoverClient(&redis.FailoverOptions{
        MasterName:    "mymaster",
        SentinelAddrs: []string{"redis-sentinel-0:26379", "redis-sentinel-1:26379", "redis-sentinel-2:26379"},
    })
err := sentinel.Set(ctx, "key", "value", 0).Err()
    if err != nil {
        panic(err)
    }
val, err := sentinel.Get(ctx, "key").Result()
    if err != nil {
        panic(err)
    }
fmt.Println("Value:", val)
}

‏راه‌اندازی Redis Sentinel روی Kubernetes با Helm

خب، بریم سر اصل مطلب و یه Helm Chart برای Redis Sentinel روی Kubernetes دپلوی کنیم.

  1. یه Helm Chart مخصوص بسازیم.
helm repo add bitnami https://charts.bitnami.com/bitnami
helm install my-redis bitnami/redis --set architecture=replication,sentinel.enabled=true

۲. بررسی وضعیت پادها

kubectl get pods


‏۳. دریافت اطلاعات Sentinel

kubectl exec -it my-redis-master-0 -- redis-cli INFO SENTINEL

‏‏مانیتورینگ Redis Sentinel با Prometheus

خیلی راحت توی values.yml چارتتون تو قسمت podAnnotations دو تا پارامتر زیر رو اضافه کنید (البته این مدلی فقط در صورتی کار میکنه که روی کلاسترتون یه Prometheus داشته باشید تا بتونه متریکای پاداتون رو Scrape کنه. اینم بعدا حس و حالش باشه مقالشو مینویسم براتون):

podAnnotations:
    prometheus.io/scrape: "true"
    prometheus.io/port: "9121"

چندتا از متریک هایی که بهمون میده:

‏- redis_master_last_io_seconds_ago : مدت زمان (به ثانیه) از آخرین ارتباط موفق بین مستر و یک رپلیکا.   
- redis_commands_processed_total : تعداد کل دستورات پردازش‌شده  .   
- redis_connected_slave_lag_seconds : لگ (به ثانیه) بین مستر و  رپلیکا.  
 - redis_connected_clients :  تعداد کلاینت‌های متصل در حال حاضر به ردیس.
 - redis_db_keys_expiring : تعداد کلیدهایی که در تمام دیتابیس‌های دارای تاریخ انقضا هستند.   
- redis_db_keys : تعداد کل کلیدهای ذخیره‌شده در تمام دیتابیس‌های.

‏در قدم آخر میتونید یه dashboard باحال توی گرافانا براش درست کنید:

برید از اینجا داشبورد رو import کنید و حالشو ببرید.



نتیجه‌گیری

حالا ما یه سیستم Redis Sentinel داریم که روی Kubernetes اجرا می‌شه و با GitLab CI/CD میتونیم پروسه دپلوی رو خودکار کنیم. تازه داریم با Prometheus و Grafana هم مانیتورش میکنیم.
این یعنی دردسر کمتر، آرامش بیشتر! 😌🔥

اگه تا اینجا اومدی، حتماً توی کامنتا نظرتو بگو! 😃