Redis مخزن بيانات مفتوح المصدر من نوع المفتاح والقيمة، يحتفظ بالبيانات في الذاكرة (RAM) بدل القرص. الجواب المختصر: أشهر استخداماته التخزين المؤقت؛ فبحفظ النتائج التي تُقرأ كثيرًا ويكلف حسابها في Redis أمام قاعدة البيانات الرئيسية، يقصر زمن الاستجابة ويخف الحمل عن القاعدة. Redis لا يحل محل قاعدة البيانات الرئيسية، بل هو طبقة سريعة أمامها.
ما هو Redis وكيف يعمل؟
يخزن Redis كل قيمة تحت مفتاح: قيمة "product:42" قد تكون نص JSON، وقيمة "cart:alice" قد تكون قائمة. ولأن القراءة تتم من الذاكرة، تكتمل القراءة الواحدة عادة في أقل من جزء من الألف من الثانية. وإلى جانب النصوص يوفر هياكل بيانات مثل القوائم والمجموعات والمجموعات المرتبة والجداول (hash) والتدفقات (streams)، لذلك يُستخدم أيضًا عدادًا ولوحة ترتيب وطابورًا بسيطًا. ويمكن إعطاء كل مفتاح مدة صلاحية (TTL)، وعند انتهائها يُحذف المفتاح تلقائيًا.
لدى Redis خيارات للكتابة على القرص (لقطات RDB وسجل AOF)، لكنه بطبيعة تصميمه ليس المكان الأساسي لحفظ السجلات. البيانات التي لا يجوز فقدها، مثل الطلبات والمدفوعات وحسابات المستخدمين، مكانها قاعدة بيانات علائقية؛ ويساعدك مقالنا PostgreSQL أم MySQL في الاختيار. أما Redis فيحمل نسخة سريعة القراءة من تلك البيانات.
ما فائدة التخزين المؤقت (cache)؟
في كل مرة تُفتح فيها صفحة منتج، تذهب الاستعلامات نفسها إلى قاعدة البيانات مرارًا. يحتفظ التخزين المؤقت بنسخة من النتيجة لفترة قصيرة ويجيب الطلبات التالية منها. والمكسب مزدوج: يحصل المستخدم على استجابة أسرع، وتتوقف القاعدة عن تكرار العمل نفسه آلاف المرات. ولا تأتي سرعة الصفحة كلها من التخزين المؤقت؛ فللصور وJavaScript وإعدادات الخادم يقدم مقالنا طرق تسريع الموقع قائمة أوسع.
في أي أعمال يُستخدم Redis؟
- تخزين مؤقت للاستعلامات وواجهات API: حفظ نتائج الاستعلامات المكلفة أو ردود الخدمات الخارجية لمدة محددة.
- مخزن الجلسات: عند تشغيل عدة خوادم، تُحفظ جلسة المستخدم في مكان واحد تقرؤه كلها.
- تحديد معدل الطلبات (rate limiting): عد الطلبات في الدقيقة لعنوان IP أو مستخدم وإيقاف من يتجاوز الحد.
- الطوابير والمهام الخلفية: وضع أعمال مثل البريد والإشعارات وإنتاج التقارير في طابور ومعالجتها في عملية منفصلة.
- لوحات الترتيب والعدادات: جداول نقاط حية بالمجموعات المرتبة، وعدادات المشاهدات والإعجابات.
- الأقفال الموزعة: منع تشغيل المهمة نفسها على خادمين في الوقت ذاته، مثل ضمان تشغيل نسخة واحدة فقط من مهمة مجدولة.
نمط cache-aside: كيف تُنشئ تخزينًا مؤقتًا باستخدام Redis؟
النمط الأكثر شيوعًا هو cache-aside (التحميل الكسول). يسأل التطبيق Redis أولًا؛ فإن وجد القيمة أعادها. وإن لم يجدها قرأ من قاعدة البيانات، وكتب النتيجة في Redis مع TTL ثم أعادها. وعند تغير البيانات تُحدَّث القاعدة أولًا ثم يُحذف المفتاح المرتبط؛ فتعيد القراءة التالية البيانات الحديثة إلى التخزين المؤقت. يوضح مثال Node.js التالي هذا التدفق:
import { createClient } from 'redis';
const redis = createClient({ url: process.env.REDIS_URL });
await redis.connect();
// Cache-aside: read from Redis first, fall back to the database on a miss.
async function getProduct(id: string, loadFromDb: (id: string) => Promise<object | null>) {
const key = 'product:' + id;
const cached = await redis.get(key);
if (cached) return JSON.parse(cached);
const product = await loadFromDb(id);
if (product) {
// A TTL keeps stale data from living forever.
await redis.set(key, JSON.stringify(product), { EX: 300 });
}
return product;
}
// On every write, the database is updated first and the cache key is removed.
async function onProductUpdated(id: string) {
await redis.del('product:' + id);
}على كل مفتاح في التخزين المؤقت أن يجيب عن سؤالين: متى ينتهي من تلقاء نفسه (TTL)، وأي عملية كتابة تحذفه؟ المفتاح الذي لا جواب لديه عن أي منهما سيعرض للمستخدم بيانات قديمة عاجلًا أو آجلًا.
أكثر أخطاء التخزين المؤقت شيوعًا
- عدم تحديد TTL: في مسار كتابة نُسي فيه الإبطال، تبقى البيانات القديمة إلى الأبد.
- حفظ بيانات خاصة بمستخدم تحت مفتاح مشترك: إذا لم يتضمن المفتاح المستخدم أو صلاحيته، فقد يرى مستخدم بيانات غيره.
- اعتبار التخزين المؤقت النسخة الوحيدة: عند إعادة تشغيل Redis أو إخراجه مفاتيح بسبب امتلاء الذاكرة، يجب أن يتعافى النظام من قاعدة البيانات.
- انتهاء مفاتيح كثيرة في اللحظة نفسها: تسقط كلها على القاعدة في الثانية ذاتها؛ وإضافة هامش عشوائي صغير إلى TTL توزع الحمل.
- تخزين كل شيء: حفظ بيانات نادرًا ما تُقرأ أو سريعة أصلًا يستهلك الذاكرة بلا فائدة.
متى تحتاج إلى Redis ومتى لا داعي له؟
في تطبيق يعمل على خادم واحد، بحركة قليلة واستعلامات سريعة أصلًا، يعني إضافة Redis مكونًا جديدًا يجب مراقبته ونسخه احتياطيًا. ابدأ بقياس الاستعلامات البطيئة، وأضف الفهارس الناقصة، وجرب تخزينًا مؤقتًا بسيطًا داخل ذاكرة التطبيق. يصبح Redis منطقيًا عندما يعمل التطبيق على عدة خوادم ويجب مشاركة الجلسات أو التخزين المؤقت، أو عندما تُقرأ البيانات نفسها مرات كثيرة في الثانية، أو عندما تكون واجهة API خارجية بطيئة أو مدفوعة لكل طلب، أو عند الحاجة إلى تحديد المعدل أو الطوابير أو الأقفال الموزعة. وأسهل طريقة لتشغيل Redis بجانب التطبيق أثناء التطوير هي الحاوية؛ راجع مقالنا ما هو Docker.
الخلاصة
Redis مخزن سريع للمفتاح والقيمة يعمل في الذاكرة، ويُستخدم غالبًا للتخزين المؤقت والجلسات والطوابير وتحديد معدل الطلبات. إذا أُعد جيدًا صار حاجزًا أمام قاعدة البيانات؛ وإذا لم تُدرس قواعد TTL والإبطال منذ البداية تحول إلى مشكلة بيانات قديمة. إذا أردت أن نقيّم معًا ما إذا كان مشروعك يحتاج فعلًا إلى طبقة تخزين مؤقت، اطّلع على صفحتي البرمجيات الخاصة وتطوير الويب أو راسلنا عبر نموذج طلب عرض سعر.