Redis Pipeline: قلل round trips قبل ما تزود السيرفرات
مستوى القارئ: متوسط
لو API عندك بيقرأ 1000 مفتاح من Redis في request واحد، هتكسب أسرع نتيجة لما تقلل عدد الرحلات على الشبكة بدل ما تزود RAM أو CPU.
المشكلة باختصار
Redis سريع جدًا في تنفيذ أوامر بسيطة. اللي بيحصل فعلاً إن التطبيق أحيانًا يخسر الوقت في الطريق بين التطبيق وRedis، مش داخل Redis نفسه. كل أمر GET منفصل يعني request يطلع، response يرجع، وبعدها الأمر اللي بعده يبدأ.
سيناريو واقعي: عندك صفحة منتجات بتعرض 1000 بطاقة. كل بطاقة تحتاج price:{id} وstock:{id} من cache. لو كتبت loop يعمل GET لكل key بالتتابع، فأنت دفعت 1000 round trip. على شبكة داخلية فيها 0.8ms RTT، الرقم النظري وحده يقترب من 800ms قبل حساب JSON parsing أو كود التطبيق.
مثال بسيط قبل التعريف العلمي
ركز في المثال ده. أنت لا تطلب من Redis أن يكون أسرع. أنت تطلب من التطبيق أن يتوقف عن سؤال Redis بنفس الطريقة البطيئة.
import Redis from "ioredis";
const redis = new Redis(process.env.REDIS_URL);
const ids = Array.from({ length: 1000 }, (_, i) => i + 1);
// الطريقة البطيئة: 1000 round trip متتالي
console.time("sequential-get");
const slow = [];
for (const id of ids) {
slow.push(await redis.get(`product:${id}:price`));
}
console.timeEnd("sequential-get");
// أفضل عندما المفاتيح مستقلة: pipeline يرسل الأوامر كدفعة
console.time("pipeline-get");
const pipeline = redis.pipeline();
for (const id of ids) {
pipeline.get(`product:${id}:price`);
}
const fast = await pipeline.exec();
console.timeEnd("pipeline-get");
// أفضل لو كل المفاتيح strings وتقدر تجيبها معًا
console.time("mget");
const keys = ids.map((id) => `product:${id}:price`);
const fastest = await redis.mget(keys);
console.timeEnd("mget");في قياس تقديري على نفس الـ VPC: 1000 GET متتالي وصلوا إلى 850ms. نفس القراءة عبر pipeline نزلت إلى 95ms. وMGET وصلت إلى 75ms لما كانت المفاتيح مناسبة لنفس العملية. الرقم مش وعد عام. هو إطار تفكير: قلل round trips أولًا، ثم قِس.
التعريف الدقيق: Pipeline وMGET بيحلوا إيه
Redis يستخدم نموذج request/response فوق TCP. الطبيعي إن العميل يرسل أمرًا وينتظر الرد. Redis pipelining يكسر النمط ده: العميل يرسل أوامر كثيرة بدون انتظار رد كل أمر، ثم يقرأ الردود مرة واحدة أو على دفعات.