السعة وتوسيع بنية البيانات التحتية
السعة وتوسيع بنية البيانات التحتية
يُعدّ تحديد حجم Redis وKafka بدقة — ومعرفة متى وكيف تتوسع — من أعلى المهارات قيمةً لدى مهندس الإنتاج. الخطأ في ذلك يعني خسارة صامتة للبيانات، أو ارتفاعات متتالية في زمن الاستجابة، أو ترحيل مؤلم للكلاستر في الساعة الثانية صباحاً. يُعلّمك هذا الدرس نماذج التحجيم وأنماط التوسعة واستراتيجيات الترقية المستخدمة في شركات تشغّل مئات التيرابايتات وملايين الرسائل في الثانية.
Redis: تحديد سعة التخزين
Redis مخزن في الذاكرة، لذا كل بايت يُحسب. معادلة التحجيم مباشرة:
- حجم مجموعة العمل: قدّر بصمة البايتات الإجمالية لجميع المفاتيح الحية باستخدام أمر
OBJECT ENCODINGوأداةredis-memory-analyzer. لا تعتمد علىINFO memoryوحده — فـused_memory_rssيتجاوز دائماًused_memoryبسبب التشتت. - نسبة التشتت: استهدف
mem_fragmentation_ratioبين 1.0 و1.5. النسب فوق 2.0 في Redis 6+ تُشغّل إزالة التشتت النشط تلقائياً، لكن تحتاج مع ذلك إلى مساحة احتياطية. - قاعدة المساحة الاحتياطية: خصّص الموارد بحيث لا يتجاوز الاستخدام في الذروة 60–70%. عقدة Redis مُحمَّلة بالكامل لا تستطيع قبول BGSAVE (تحتاج ~100% من الذاكرة المستخدمة لصفحات CoW) دون الانتقال للتبديل، مما يدمر زمن الاستجابة.
لـتحجيم الإخلاء، اضبط maxmemory على 75% من الذاكرة المتاحة واختر سياسة الإخلاء قبل أن تحتاجها. الإعداد الافتراضي لأعباء عمل التخزين المؤقت في شركات التقنية الكبرى هو allkeys-lru؛ لمخازن الجلسات استخدم volatile-lru حتى تكون فقط المفاتيح ذات TTL مؤهلة للإخلاء. لا تترك maxmemory على 0 في بيئة مشتركة — سيُنهي OOM Killer العملية دون تحذير.
Redis: أنماط التوسعة
هناك ثلاثة محاور للتوسعة في Redis:
- التوسعة الرأسية: الانتقال إلى مثيل أكبر. مباشرة لكن محدودة. فوق ~256 جيجابايت من الذاكرة، يصبح BGSAVE المبني على fork بطيئاً بشكل مؤلم؛ فكّر في تعطيل RDB واستخدام AOF على النسخة المتماثلة فقط.
- توسعة القراءة عبر النسخ المتماثلة: وجّه الأوامر للقراءة فقط إلى النسخ المتماثلة باستخدام تفضيل القراءة من جانب العميل أو وكيل (Envoy أو Twemproxy). النسخ المتماثلة تُضيف تأخيراً في التكرار؛ لا توجّه قراءات تتطلب تسلسلية إلى نسخة متماثلة أبداً.
- التقسيم الأفقي عبر Redis Cluster: 16,384 فتحة تجزئة موزّعة على عدد من العقد الأساسية. الحد الأدنى للكلاستر هو 3 عقد أساسية + 3 نسخ متماثلة. استهدف ≤200 جيجابايت من مجموعة العمل لكل شريحة أساسية بقاعدة 70% احتياطي. إعادة التشريح تتم أونلاين لكنها مكثفة على المعالج — جدولها في أوقات انخفاض حركة المرور.
redis-cli --cluster reshard <host>:<port> بصورة تفاعلية، أو أتمتها بـ--cluster-from all --cluster-to <target-id> --cluster-slots <N> --cluster-yes. شغّلها في أوقات الذروة المنخفضة. راقب cluster_state وcluster_slots_assigned في INFO cluster طوال العملية. إعادة التشريح الفاشلة تترك الفتحات في حالة migrating — أكمل أو أجهض بـCLUSTER SETSLOT <slot> STABLE.
Kafka: تحديد سعة التخزين
تحجيم Kafka له ثلاثة أبعاد مستقلة: الإنتاجية، التخزين، والأقسام.
- الإنتاجية: وسيط Kafka واحد على عتاد حديث يتعامل مع 200–600 ميجابايت/ثانية من الإنتاجية الإجمالية للكتابة. قِس معدل البايتات الفعلي للمنتجين بـ
kafka.server:type=BrokerTopicMetrics,name=BytesInPerSec. الاختناق دائماً في بطاقة الشبكة أو معدل كتابة القرص، ليس المعالج. - التخزين: إجمالي البايتات =
معدل_الرسائل × متوسط_حجم_الرسالة × ساعات_الاحتفاظ × عامل_التكرار. أضف 20% لملفات الفهرس. استخدمkafka-log-dirs.shلقياس استخدام القرص الفعلي لكل موضوع/قسم. - عدد الأقسام: ابدأ بـ
max(الإنتاجية_المستهدفة / إنتاجية_القسم_الواحد، توازي_المستهلكين). الإفراط في التقسيم له تكاليف حقيقية: مزيد من واصفات الملفات المفتوحة، انتخاب قائد أطول، وضغط أكبر على بيانات ZooKeeper/KRaft. تحدّ LinkedIn وGoogle تاريخياً عدد الأقسام لكل وسيط بـ4,000.
Kafka: أنماط التوسعة
يتوسع Kafka أفقياً بإضافة وسطاء وإعادة توزيع قيادة الأقسام. العملية:
- أضف وسطاء جدداً إلى الكلاستر (يلتحقون بسجلات فارغة).
- شغّل أداة إعادة التخصيص (
kafka-reassign-partitions.sh) لتوليد وتنفيذ خطة إعادة توزيع تنشر النسخ عبر مجموعة الوسطاء الموسّعة. - راقب تقدم التكرار بـ
kafka-reassign-partitions.sh --verify. قيّد معدل التكرار بالشبكة لتجنب تجويع المنتجين: اضبطleader.replication.throttled.rateوfollower.replication.throttled.rateعلى المواضيع المتأثرة قبل البدء.
استراتيجيات الترقية
لكل من Redis وKafka مسارات ترقية متجددة موثّقة. القاعدة الأساسية: لا تقفز فوق الإصدارات الرئيسية أبداً.
ترقية Redis المتجددة: رقّ النسخ المتماثلة أولاً، ثم أجرِ إخفاقاً اختيارياً نحو نسخة متماثلة (باستخدام أمر FAILOVER في Redis 6.2+ أو CLUSTER FAILOVER)، ثم رقّ العقدة الأساسية السابقة. لإعدادات Sentinel، أطلق إخفاقاً يدوياً بـSENTINEL FAILOVER <master-name> بعد ترقية جميع النسخ المتماثلة.
ترقية Kafka المتجددة: رقّ وسيطاً واحداً في كل مرة. اضبط inter.broker.protocol.version وlog.message.format.version على الإصدار الحالي قبل البدء حتى يبقى الكلاستر متوافقاً مع البروتوكول خلال الانتقال. ارفع هذه القيم فقط بعد أن تنتهي جميع الوسطاء من الانتقال للإصدار الجديد.
التخطيط للسعة عملياً
تعامل مع سعة بنية بياناتك تماماً كما تتعامل مع سعة عقد Kubernetes: نمذجها، وأنذر عليها، وخطّط للترقيات قبل بلوغ 70% من الاستخدام. المقاييس الرئيسية لتتبعها في منظومتك الرقابية (لديك بالفعل Prometheus/Grafana من دروس سابقة):
- Redis:
redis_memory_used_bytes / redis_memory_max_bytes،redis_evicted_keys_total،redis_connected_clients - Kafka:
kafka_server_brokertopicmetrics_bytesinpersec،kafka_log_log_size،kafka_controller_kafkacontroller_activecontrollercount، متأخر مجموعة المستهلكين عبرkafka_consumer_group_lag
retention.bytes على مستوى الموضوع (ليس فقط retention.ms) كسقف صارم حتى لا يملأ موضوع جامح أقراصك بينما مهندس المناوبة يتلقى تنبيهاً.