PHP 8.2 وRedis: لماذا تختفي الجلسات بعد إعادة تشغيل العامل

这篇内容暂时只有 العربية 版本,以下是原文。

خادم Ubuntu 22.04، PHP 8.2 FPM، Redis 7 على نفس الجهاز، وجلسات PHP مخزّنة في Redis عبر phpredis. عدد المستخدمين المتزامنين حوالي 4000، ومدة الجلسة 30 دقيقة. المشكلة ظهرت بعد نشر جديد: جزء من المستخدمين يفقد جلسته فجأة، لا 401 جماعي، بل 2-5% من الطلبات. أعدنا التشغيل فاختفى العَرَض ثم عاد بعد ساعات.

الخطوة الأولى كانت مقارنة ما يكتبه PHP بما يقرأه. في php.ini كان:

session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379?database=2&timeout=1"
session.gc_maxlifetime = 1800

ثم فحصت المفاتيح فعليًا:

redis-cli -n 2 --scan --pattern 'PHPREDIS_SESSION:*' | head
redis-cli -n 2 ttl PHPREDIS_SESSION:abc123

الـTTL كان يتراوح بين 1440 و1800 ثانية، أي أن gc_maxlifetime ليس مصدر المشكلة. المشكلة كانت في maxmemory-policy على Redis: allkeys-lru. أي أن Redis يطرد أي مفتاح، بما فيه الجلسات، عند الضغط. مع 4000 مستخدم وذاكرة 512MB، كانت الجلسات تُطرد قبل انتهاء صلاحيتها.

الحل لم يكن زيادة الذاكرة فقط، بل فصل سياسة الطرد:

maxmemory 2gb
maxmemory-policy volatile-lru

مع volatile-lru يطرد Redis فقط المفاتيح التي لها TTL، والجلسات لها TTL، لكن بقي خطر طردها. لذلك نقلت الجلسات إلى قاعدة مستقلة على منفذ آخر مع maxmemory-policy noeviction، وضبطت session.gc_probability = 0 لأن Redis يتولى الانتهاء عبر TTL، وتجنّب تصادم GC بين عدة عمال FPM.

المقابل: noeviction تعني أن الكتابة تفشل عند الامتلاء، لذا راقبنا used_memory وأضفنا تنبيهًا عند 75%. وفصل قاعدة الجلسات يعني نسخًا احتياطيًا منفصلًا وإدارة اتصالات إضافية.

حدود ما سبق: إذا كان التطبيق يخزّن مفاتيح بلا TTL في نفس القاعدة، فإن noeviction سيوقف الكتابات كلها عند الامتلاء. وإذا كان النشر يعيد تشغيل Redis نفسه، فالجلسات ستختفي بغض النظر عن السياسة. جربت أيضًا session.lazy_write = 1 فقلل الكتابات لكنه لا يحمي من الطرد. ما زلت غير متأكد من سلوك volatile-lru عند اقتراب الذاكرة من الحد في Redis 7.2 تحديدًا، ولم أختبره تحت حمل حقيقي كافٍ.

سؤالي: هل تفصلون جلسات Redis في قاعدة/منفذ مستقل، أم تعتمدون على volatile-* مع مراقبة الذاكرة فقط؟ وما الذي كسر عندكم أولًا عند الطرد؟

0
赞同度 100% · 0 条评论 · 6 阅读

0 条评论

支持 Markdown · 回复会实时推送给对方

还没有评论,写下第一条。