Redis بياكل 8GB من الـ RAM؟ خفّضه لـ 2GB في 4 خطوات بدون ما تخسر داتا
لو الـ Redis instance عندك بياكل 8GB والـ AWS bill بيرتفع كل شهر، المشكلة 9 مرات من 10 مش في حجم الداتا الحقيقي، دي في طريقة تخزينها. هتشوف هنا 4 تعديلات قابلة للتطبيق في 30 دقيقة، بأرقام قبل وبعد من حالة إنتاج فعلية.
المشكلة باختصار
Redis مش بيخزن قيمتك في byte واحد على RAM. كل key بياخد overhead حوالي 50–80 byte حتى لو الـ value فيه رقم واحد. لو عندك مليون key صغير، ده 60–80MB ضايعين على metadata قبل ما تحسب الـ values نفسها. الموضوع بيتفاقم لما تستخدم data structures غلط: hash كبير بدل ziplist، أو مليون string منفصل بدل hash واحد منظم.
مثال للمبتدئين: قصة الدُرج المعدني
تخيل عندك دُرج كبير في المطبخ، ومعاك 500 ملعقة شاي صغيرة. لو حطيت كل ملعقة في علبة بلاستيك مستقلة، الدُرج هيمتلي بـ 50 ملعقة بس، ولو فتحته هتلاقي 90% منه عبارة عن علب فاضية وفقاعات هواء. لكن لو رصصت الـ 500 ملعقة جنب بعض في تقسيمة واحدة منظمة، هتاخد رف واحد بس وفيه مكان للسكاكين كمان.
Redis نفس المنطق بالظبط. كل ما عملت SET user:123:name "Ahmed" منفصل، Redis بيفتح "علبة بلاستيك" كاملة (redisObject + dictEntry + SDS header). لكن لما تستخدم HSET user:123 name "Ahmed" age "30" city "Cairo"، الثلاث قيم بيتحطوا في "تقسيمة" واحدة compact اسمها listpack، والـ overhead بينزل من 200 byte لـ 30 byte.
التعريف العلمي بالظبط
كل key في Redis بيتمثل بـ struct اسمه redisObject فيه: type (4 bits)، encoding (4 bits)، LRU/LFU info (24 bits)، refcount (32 bits)، pointer للـ value (64 bits). ده 16 byte ثابتين. زائد ده، كل key بيتسجل في hash table رئيسي عن طريق dictEntry اللي بياخد 24 byte (key pointer + value pointer + next pointer). زائد SDS header للـ key string نفسه (5 bytes للنوع المضغوط).
مجموع الـ overhead قبل أي داتا فعلية: حوالي 50–80 byte لكل key. الحل اللي هتشوفه تحت بيستغل feature اسمه listpack encoding (بديل ziplist في Redis 7+) اللي بيخزن مجموعة values صغيرة في contiguous memory block واحد بدل ما كل واحدة تاخد object منفصل.
الخطوة 1: قِس الاستهلاك الحقيقي قبل ما تعدّل
ممنوع تعدّل أي حاجة قبل ما تشغّل القياس. السبب: التحسين بدون قياس بيخلّيك تخسر يوم في حاجة مش هي المشكلة الفعلية. شغّل الأوامر دي بالترتيب:
# ١) نظرة عامة على استهلاك الذاكرة
redis-cli INFO memory | grep -E "used_memory_human|fragmentation_ratio|maxmemory_human"
# ٢) إحصائيات تفصيلية
redis-cli MEMORY STATS
# ٣) أكبر 100 key (بياخد دقيقة على instance كبير)
redis-cli --bigkeys
# ٤) عيّنة على استهلاك الذاكرة لكل key
redis-cli --memkeys --memkeys-samples 0