انتهاء مهلة اتصال Redis: ماذا يعني وكيف تصلحه
يجيب Redis في ميكروثوانٍ — حتى يجعل أمرٌ بطيء واحد أو fork للحفظ أو شبكة مشبعة كلَّ العملاء ينتظرون. هنا تتعلّم كيف تكتشف أيها السبب.
ماذا يعني انتهاء مهلة Redis فعليًا
انتهاء مهلة اتصال Redis يعني أن عميلك انتظر أطول من حدّه المضبوط — إما لإنشاء اتصال TCP (مهلة الاتصال) أو لاستلام رد على أمر (مهلة القراءة/الأمر). والتمييز مهم: مهلة الاتصال تشير إلى المسار الشبكي أو DNS أو خادم لا يستطيع قبول الاتصالات؛ أما مهلة الأمر فتعني عادة أن Redis قَبِلك لكنه كان أشغل من أن يجيب في الوقت.
والحقيقة المعمارية خلف معظم مهلات الأوامر: يُنفّذ Redis الأوامر على خيط واحد. عملية بطيئة واحدة — مسح KEYS عبر ملايين المفاتيح، أو SMEMBERS على مجموعة ضخمة، أو سكربت Lua في حلقة — تحجب كل العملاء الآخرين حتى تنتهي. وبالمثل، يقوم الحفظ الخلفي (لقطات RDB وإعادة كتابة AOF) بعمل fork للعملية، وعلى بيانات كبيرة أو مضيف شحيح الذاكرة قد يوقف ذلك الـ fork الخادم بشكل ملحوظ.
الأسباب الجذرية الشائعة لمهلات Redis
مشاكل شبكة أو جدار ناري أو DNS
فقدان حزم بين التطبيق وRedis، أو مجموعة أمان تحجب المنفذ 6379، أو حلّ DNS بطيء لاسم مضيف Redis، أو تأخير بين المناطق بعد أن نقل failover الخادمَ الرئيسي. مهلات الاتصال مع مقاييس سليمة على جهة الخادم تقع هنا في الغالب.
أوامر بطيئة تحجب الخيط الوحيد
KEYS على فضاء مفاتيح كبير، أو SMEMBERS/HGETALL على هياكل ضخمة، أو دفعات MGET هائلة، أو سكربتات Lua ثقيلة. وبينما يعمل أحدها، تصطف أوامر بقية العملاء خلفه — فتظهر المهلات على أوامر بريئة وتُخفي الجاني الحقيقي. وSLOWLOG يسمّيه.
توقفات الحفظ: ضغط fork والقرص
يقوم BGSAVE وإعادة كتابة AOF بعمل fork للعملية؛ ومع بيانات كبيرة يستغرق الـ fork نفسه وقتًا، ويضاعف copy-on-write ضغطَ الذاكرة. والأقراص البطيئة تجعل fsync الخاص بـ AOF يحجب (راقب aof_delayed_fsync). والعرَض: قفزات مهلات دورية تتطابق مع جداول الحفظ.
استنفاد الاتصالات: maxclients وعواصف الاتصال
التطبيقات بلا تجميع اتصالات تفتح اتصالًا جديدًا مع كل طلب؛ وتحت الضغط تُغرق آلاف المصافحات الخادمَ، أو يبلغ connected_clients حدَّ maxclients (افتراضيًا 10000) فيُصدّ العملاء الجدد. راقب rejected_connections في INFO stats لتجد الدليل القاطع.
كيف تحقّق في مهلات Redis وتصلحها
صنّف المهلة (اتصال أم أمر)، ثم استجوب Redis نفسه — فأدوات SLOWLOG وINFO وLATENCY المدمجة تحدّد السبب عادة خلال دقائق.
- 1
صنّف: مهلة اتصال أم مهلة أمر؟
اقرأ خطأ العميل بدقة — فمعظم المكتبات تميّز «connection timed out» عن «timeout awaiting response». فشل الاتصال يرسلك إلى الشبكة وتوفّر الخادم؛ ومهلات الاستجابة ترسلك إلى الأوامر البطيئة والحفظ والحمل على مضيف Redis.
- 2
اختبر الوصول وزمن الاستجابة الأساسي
من جهاز التطبيق: redis-cli -h <host> PING ثم redis-cli --latency لقياس حيّ للذهاب والإياب. الأرقام الأحادية بالميلي ثانية صحية؛ أما الزمن المرتفع أو المتقلّب من جهاز التطبيق دون مضيف Redis نفسه فيعزل المسار الشبكي.
- 3
اقرأ SLOWLOG
يعرض SLOWLOG GET 25 أبطأ الأوامر الأخيرة بمدتها ومعاملاتها. نمط KEYS أو HGETALL عملاق أو سكربت ثقيل عند أوقات مهلاتك هو الجاني. استبدل KEYS بـ SCAN التدريجي، وفكّك الهياكل الضخمة، وحدّد سقفًا لأحجام الدفعات.
- 4
افحص العملاء وأعداد الاتصالات
يعرض INFO clients قيمة connected_clients مقابل maxclients؛ ويعرض INFO stats قيمتي rejected_connections وtotal_connections_received. معدل إنشاء اتصالات هائل يعني غياب التجميع؛ وتصاعد rejected_connections يعني بلوغ maxclients — أصلح التجميع أولًا، وارفع الحد ثانيًا.
- 5
افحص الحفظ وضغط المضيف
يعرض INFO persistence قيمة latest_fork_usec (كم أوقف آخر fork الخادم) وaof_delayed_fsync (حجب fsync بسبب قرص بطيء). وعلى المضيف افحص الذاكرة (فالـ swapping قاتل لزمن استجابة Redis) وسرقة المعالج في الأجهزة الافتراضية ودخل/خرج القرص أثناء نوافذ اللقطات. ووائم جداول الحفظ مع فترات انخفاض المرور أو انقلها إلى replica.
- 6
اضبط مهلات العميل وإعادة المحاولة عن قصد
بعد إصلاح السبب، اضبط مهلات اتصال وأوامر تعكس الواقع (منخفضة لكن فوق p99 لديك)، وفعّل التجميع بحجم محدود، وأضف إعادة محاولة بتراجع تدريجي للتعثرات العابرة — حتى يتدهور التوقف القصير القادم بلطف بدل أن يتسلسل.
كيف تمنع مهلات Redis
- امنع KEYS في مراجعات شيفرة الإنتاج — استخدم SCAN، وصمّم هياكل البيانات بحيث لا يلمس أمر واحد ملايين المفاتيح.
- استخدم تجميع الاتصالات على جهة العميل في كل مكان؛ فأنماط اتصال-لكل-طلب تنهار تحديدًا عند ذروة المرور.
- راقب زمن استجابة Redis ونمو slowlog وconnected_clients وrejected_connections — فكلٌّ منها إنذار مبكر لنمط فشل مختلف.
- اضبط الذاكرة بحيث تتسع للـ forks: أبقِ used_memory أدنى من ذاكرة المضيف بهامش مريح، ولا تدع مضيف Redis يلجأ إلى swap أبدًا.
- جدوِل لقطات RDB وإعادة كتابة AOF بعيدًا عن ذروة المرور، أو انقل الحفظ عن الخادم الرئيسي كليًا إلى replica.
كيف يساعدك AllStak مع مشاكل Redis
تغطي مراقبة البنية التحتية في AllStak مؤشرات مضيف Redis الحيوية — الذاكرة والمعالج ودخل/خرج القرص والشبكة — وهناك تُفسَّر معظم مهلات Redis في النهاية: مضيف بدأ يستخدم swap، أو قرص تباطأ أثناء اللقطات، أو ضغط ذاكرة جعل الـ forks مكلفة. والرسوم الاتجاهية تجعل نمط التوقف الدوري للحفظ مرئيًا بنظرة.
وتصل استثناءات المهلة من تطبيقك إلى تتبّع الأخطاء مجمَّعة وموقوتة، فتصفّها مقابل مقاييس المضيف وسجلاتك من الدقائق نفسها — بما فيها أسطر سجل Redis إن كنت ترسلها. وهذا الربط يجيب بسرعة عن سؤال الفرز الأول: هل هي الشبكة أم المضيف أم أمر سيئ واحد؟
أسئلة شائعة عن مهلات Redis
لماذا أمر KEYS خطير إلى هذا الحد في الإنتاج؟
يمسح KEYS فضاء المفاتيح كاملًا في نداء واحد حاجب على خيط أوامر Redis الوحيد. ومع ملايين المفاتيح يعني ذلك مئات الميلي ثوانٍ إلى ثوانٍ لا يتلقى خلالها أي عميل آخر ردًا — انقطاع تُحدثه بيدك. استخدم SCAN الذي يمرّ على دفعات صغيرة بمؤشر يداخلها الخادم مع بقية العمل.
هل تعني المهلة أن Redis متوقّف؟
عادة لا. توقّف Redis ينتج غالبًا «connection refused» — رفضًا فعّالًا. أما المهلة فتعني أن Redis (أو الشبكة) كان أبطأ من أن يجيب في الوقت: خيط أوامر محجوب، أو توقف fork، أو تشبّع، أو فقدان حزم. افحص PING من جهاز التطبيق وSLOWLOG قبل افتراض الانقطاع.
هل أكتفي بزيادة مهلة العميل؟
نادرًا ما تكون الإصلاح الأساسي. يجيب Redis عادة في أقل من ميلي ثانية بكثير، فالمهلة السخية بما يكفي لإخفاء خادم محجوب تعني تكدّس طلباتك منتظرةً بدل الفشل السريع. اعثر على سبب التوقف أولًا؛ ثم اضبط المهلات فوق p99 المقيس بقليل مع إعادة محاولة للتعثرات الحقيقية.
كيف يبدو بلوغ حد maxclients؟
تتلقى الاتصالات الجديدة "ERR max number of clients reached" (أو تفشل أثناء الاتصال، وقد تُظهرها العملاء المجمَّعون كمهلات)، بينما تواصل الاتصالات القائمة عملها. ويعرض INFO clients بلوغ connected_clients الحدَّ وتصاعد rejected_connections. الإصلاح الدائم هو تجميع الاتصالات؛ ورفع maxclients ينقل الجدار فحسب.
شاهد التوقف خلف مهلات Redis لديك
يضع AllStak ذاكرة مضيف Redis وقرصه ومعالجه بجانب أخطاء المهلة وسجلات تطبيقك — فيبدأ الفرز بالأدلة لا التخمين.