أكاش إمتى؟قراءة أكتر من الكتابة، query غالية، نفس البيانات بتتطلب، وتستحمل تبقى قديمة شوية
مكاشش إمتى؟كتابة كتير، consistency قوية (فلوس/مخزون وقت الدفع)، hit rate واطي، بيانات فريدة لكل يوزر
حمل الداتابيزQPS × miss rate، ومن 95٪ لـ 99٪ hit يقلل الحمل 5 مرات
الداتابيز تصغر؟لأ، لازم تستحمل كاش فاضي (restart، deploy، hot key)
النمط الافتراضيcache-aside: GET، لو miss هات من DB و
SET key val EX ttlnull من ioredisيعني مش موجود، فاكتب cached !== null مش if (cached)write-throughاكتب في DB والكاش مع بعض، الكاش حديث بس الـ write أبطأ
write-behindاكتب في الكاش والـ DB بعدين، سريع بس ممكن تضيع بيانات
write-aroundاكتب في DB بس، والكاش يتملي وقت القراءة
الـ TTLعلى قد ما القيمة تستحمل تبقى قديمة، ودايمًا موجود كشبكة أمان
اسم الـ key
نوع:version:id، وأي حاجة بتغيّر النتيجة جوه الـ keyغيّرت شكل الـ objectزوّد الـ version:
product:v1 ← product:v2وقت الكتابة
UPDATE الأول وبعدين DEL، والمسح أأمن من التحديثقيمة قديمة بعد المسحrace بين قراءة بطيئة والمسح، فاعمل delayed double delete
مسح مجموعة keysversioned namespace:
INCR category:5:versionحد بيكتب من بره التطبيقCDC (Debezium / WAL) يمسح الكاش
الـ stampedehot key خلص، آلاف miss مع بعض، الداتابيز بطّأت، الـ pool اتملى
عدد الـ missesQPS × وقت الـ query، وبيكبر لما الداتابيز تبطّأ
pg بيستنى للأبدdefault
connectionTimeoutMillis هو 0، فحط قيمةretry stormrefresh + retries تلقائية بتضاعف الحمل وقت الضعف
جوه الـ processsingle-flight: Map للـ Promise اللي شغالة +
finally يمسحبين الـ instances
SET lock:key token NX PX 5000 في أمر واحدفك الـ lockLua: امسح بس لو القيمة هي الـ token بتاعك
بعد ما تاخد الـ lockdouble-check: اقرا الكاش تاني قبل الـ query
المستنيينpoll بـ backoff + jitter لحد
waitMs، أو stale، أو fallbackالـ lock TTLأطول من أطول query، ومعاه
statement_timeoutRedlockمش محتاجه للكاش، أسوأ حاجة 2 queries بدل 1
الـ jitter
ttl ± 10–20%، أو ينقص بس لو فيه حد أقصى للقدمالـ avalanchekeys كتير خلصت مع بعض أو الكاش وقع: jitter + warming
الـ jitter والـ hot keyمش كفاية، محتاج lock أو refresh قبل الـ expiry
stale-while-revalidatesoft TTL جوه القيمة + hard TTL في Redis، ورجّع القديم وجدد في الخلفية
XFetchجدد لو
now - delta × beta × ln(rand) >= expiry، ومعاه single-flightrefresh-aheadjob بـ lock بيجدد الـ hot keys المعروفة قبل ما تخلص
never expireللإعدادات والـ flags، مع job بيصلّح أو TTL طويل
بعد deploycache warming للـ hot keys بـ batches وjitter
Redis نفسه سخنL1 بـ
lru-cache وTTL ثانية أو اتنينnode واحدة في Cluster سخنةانسخ الـ key على كذا slot أو اقرا من الـ replicas
الـ pool
max صغير، connectionTimeoutMillis قصير، statement_timeoutحساب الـ maxinstances × max أقل من
max_connections، أو PgBouncerالـ timeoutsاللي جوه أقصر من اللي بره
load shedding
pool.waitingCount عالي ← 503 + Retry-After على طولcircuit breakerclosed ← open بعد أخطاء ← half-open يجرّب ← closed
bulkheadspool منفصل للحاجات المهمة زي checkout
retries2–3 مرات، backoff أُسّي، full jitter، في طبقة واحدة
penetrationkeys مش موجودة:
__null__ بـ TTL قصير + bloom filter + validationbloom filterلأ = أكيد مش موجود، آه = غالبًا موجود
breakdownاسم تاني للـ hot key اللي خلص = المشكلة الأساسية
Redis وقع
commandTimeout قصير، enableOfflineQueue: false، وsingle-flight وbreaker قدام DBbig keys
--bigkeys، قسّمها، وامسح بـ UNLINKأهم metrichit ratio لكل نوع key، وmisses في الثانية
أبكر إنذار
pool.waitingCount أكبر من صفرhot keys
redis-cli --hotkeys مع LFU، أو اعدّ في الكودlabels الـ metricsنوع الـ key مش الـ id
خلّصت المذكرة لما
🧠 اختبر نفسك
١) hot key بـ 10,000 read في الثانية، والـ TTL بيخلص كل 5 دقايق والداتابيز بتضرب. أقل حاجة تعملها؟
single-flight + lock موزّع بـ SET NX PX، وأحسن منها stale-while-revalidate عشان محدش يستنى.
٢) كل ساعة بالظبط الداتابيز بتضرب دقيقة. والـ hot keys محمية. المشكلة غالبًا؟
avalanche: keys كتير بنفس الـ TTL اتملت مع بعض. الحل jitter.
٣) Redis وقع، إيه اللي يمنع الداتابيز تقع وراه؟
timeouts قصيرة على Redis، وsingle-flight جوه الـ process، وcircuit breaker، وload shedding، وL1 cache.