المقدمة
كلنا عارفين إن Redis واحدة من أسرع الـ Key-Value Stores اللي موجودة في الساحة، وأكتر استعمالتها بيكون في الـ Caching وعشان كده أكيد جه في دماغ أي حد بيستخدمها سؤال مهم: "لو حصل crash للسيرفر، إيه اللي هيحصل للداتا؟"
والإجابة هنا بتكون: على حسب إحنا مشغلين أنهي طريقة من طرق الـ Persistence (الحفاظ على البيانات) اللي Redis بتوفرها.
فورقة وقلم وتعالوا نفهم مع بعض:
- يعني إيه Persistence أصلاً؟
- إيه الأنواع اللي Redis بتوفرها؟ والفرق بينهم؟
- أستخدم أنهي واحدة؟
Data Persistence
الـ Data Persistence معناها إن الـ data اللي في الذاكرة (RAM) ما تضيعش لما السيرفر يوقع أو يحصل فيه مشاكل أو حتى يحصله restart. وكلنا عارفين إن redis شغالة أساسًا in-memory، وده معناه إنها سريعة جدًا بس عرضة لتضيع كل البيانات لو ما فيش backup نقدر نسترجع بيه البيانات دي.
عشان كده Redis بتوفرلنا طريقتين رئيسيتين لحفظ الداتا:
1. RDB (Redis Database)
2. AOF (Append Only File)

RDB Snapshotting
في الطريقة دي Redis بتعمل snapshot من كل الداتا الموجودة في الذاكرة (RAM) وتحطها في ملف .rdb.
ازاي الـ RDB بيشتغل؟
كل شوية (حسب الـ config أو من خلال manual trigger)، Redis بتاخد نسخة Snapshot من كل البيانات اللي موجودة وتكتبها في ملف على الـ disk. فلو حصل crash لأي سبب من الأسباب للـ redis instance .. تقدر تعمل restore للداتا بشكل طبيعي من آخر snapshot حصل.
- فالأول Redis بتعمل
fork(): فبيكون عندنا Parent / Child Process الـ Parent Process بتقدر تستقبل read/write requests بشكل طبيعي جدًا، في حين إن الـ child process اللي حصلها fork بتبدأ تكتب الـ snapshot في ملف مؤقّت على الـ disk. - بعد ما الـ child process يخلص، الملف المؤقّت بيتغيّر للـ
dump.rdbبشكل آمن. - العملية دي بتستخدم كمان الـ copy-on-write علشان تقلل التأثير على الأداء خصوصًا لو كان حجم البيانات كبير فتقدر تنقل البيانات بشكل فعال.
مميزات الـ RDB
- سريع جدًا في عملية الـ restore وكمان بيحافظ على كفاءة Redis بشكل كبير لان الـ Parent Process مش بتشغل بالها بعملية الـ I/O اطلاقًا ولكن دي مهمة الـ child process.
- مناسب للـ backups خصوصًا لو بناخد snapshot على فترات فهيبقى معانا نسخة من البيانات كل فترة وده هيكون مساعد جدًا لو حبينا نعمل backup في لحظات زمنية معينة.
- الملف بيكون صغير في الحجم وبالتالي بيسهل التعامل معاه ونقله خصوصا بين الـ Data Centers وبعضها في حالة الـ Disaster Reocvery.
مشاكل الـ RDB
رغم إن الـ RDB ليه مميزات كتير ولكن بما إنه snapshot بيتاخد على intervals معينة ، فده يخليه عرضة للآتي:
- لو حصل crash بعد آخر snapshot، الداتا الجديدة اللي لسه محصلهاش snapshot هتضيع.
- عملية الـ fork مع حجم بيانات كبير ممكن يخلي في شوية بطء يتسبب في الـ Parent Process يتأخر شوية على مايرد على الـ clients طب ليه ؟
- عملية الـ fork بتخلي الـ OS يضطر يعمل شوية حاجات زي نسخ الـ metadata الخاصة بالـ Process زي الـ memory/threads/descriptors وغيرها فمع حجم بيانات كبيرة ده هيكون حمل على الـ CPU وبالتالي هيأثر بشكل ما على الـ Parent Process.
مثال من الـ RDB Config
save 900 1 # لو اتغير key واحد خلال 900 ثانية، خد snapshot
save 300 10 # لو اتغير 10 keys خلال 5 دقايق
AOF (Append Only File)
الطريقة دي بتخلي Redis يكتب كل عملية write بتحصل (زي set, del) في ملف log. بمعنى أدق كل الـ commands اللي حصلت بتتكتب في الـ .log وبتتخزن على الـ Disk.
ازاي الـ AOF بيشتغل؟
كل ما يحصل أي تعديل في الداتا، Redis بتكتب الـ command اللي حصل في آخر ملف الـ AOF. بشكل append-only ولما يحصل وليكن restart أو crash، تقدر وقتها تقرأ كل العمليات اللي في الملف ده واحدة واحدة وترجع الداتا.
طب ايه مدى الـ Durability اللي الـ AOF بيوفرها؟
الـ AOF بيوفر أكتر من طريقة للـ Durability من خلال التحكم في الـ appendfsync ودي عبارة عن configuration بنتحكم فيها ، ودي بكل بساطة اللي بتروح تعمل flush على الـ disk بالـ commands اللي موجودة في الـ Buffer وطبعًا redis بيخلي ده يتم في الـ background عشان ما يأثرش على الـ main thread.
فيه عندنا أكتر من نوع وكل واحد ليه الـ trade-offs بتاعته زي always ودي معناها مع كل عملية write operation على الـ Redis محتاجين نعمل fsync وبالتالي ده هيكون بطيئ جدًا جدًا لإن مع كل عملية احنا محتاجين نـ flush للـ commands اللي حصلت على الـ Disk.
وفيه خيار تاني اننا نخليها مثلًا كل ثانية ، فمع كل ثانية بيكون فيه background process هتبدأ تعمل fsync للـ commands اللي موجودة في الـ Buffers.
مميزات الـ AOF
- أكثر أمانًا، لأننا ممكن نختار نكتب في الـ AOF بعد كل عملية زي ما وضحنا في الـ
appendfsyncوبالتالي مانفقدش أي بيانات. - مفيش خوف من إن يحصل Corruption للبيانات المتخزنة في الـ AOF وحتى لو حصل power outage اثناء الكتابة على الـ disk ، فـ redis عندها checks بتعملها عشان تفهم ايه الامر اللي كان بيحاول انه يتكتب.
- من ضمن مميزات Redis هي حاجة اسمها الـ Log Rewriting ودي معناها إن بدل مايكون عندي الـ AOF فيه مثلا 1,000 عملية تمت على الـ key فممكن تختزل ده كله بعملية واحدة بالقيمة الآخيرة اللي فيه ، وبتعمل ده من خلال الـ
forkكذلك وممكن نتكلم عنها بعدين.
مشاكل الـ AOF
- الملف بيكبر بسرعة وبيكون حجمه كبير جدًا.
- أبطأ شوية من الـ RDB في عملية الـ restore بسبب كبر الملف وإن العمليات اللي فيه ممكن تبقى كبيرة.
- محتاج عملية الـ
rewriteكل فترة عشان تصغر من حجم الملف.
مثال من الـ AOF Config
appendfsync always # كل عملية تتكتب فورًا (أمان عالي، performance أقل)
appendfsync everysec # كل ثانية (default، وبيقدم توازن)
appendfsync no # سيب السيستم يتحكم (أداء أحسن، بس أقل أمان)نستخدم الـ RDB ولا الـ AOF؟
اختيار الـ Persistence Configuration بيختلف من حالة للتانية وكل واحدة زي ما شوفنا ليها الـ trade-offs اللي ممكن تكون مناسبة في نظام ومش مناسبة ابدًا في نظام تاني بناء على المتطلبات. فخلونا نشوف مع بعض مقارنة سريعة بين الاتنين:
| المقارنة | RDB | AOF |
|---|---|---|
| السرعة | أسرع في الـ restore | أبطأ شوية |
| الأمان | ممكن تفقد شوية داتا | أقل فقد ممكن |
| الحجم | أصغر | بيكبر بسرعة |
| طريقة التشغيل | كل شوية snapshot | كل عملية write بتتسجل |
Redis Database + Append Only File
من ضمن الاختيارات اللي Redis بتقدمها هي إننا نقدر نشغل الـ RDB + AOF في نفس الوقت مع بعض ويبقى حققنا أقصى استفادة ممكنة. ففي الحالة دي، لو حصل restart مثلًا، هنلاقي إن Redis هتستخدم AOF لأنه بيكون أحدث. وفي نفس الوقت احنا عندنا snapshot للبيانات من فترة للتانية لو حبينا ناخد backup من فترة معينة.
ونقدر برضو نستعمل الـ snapshot في اننا نرجع البيانات بسرعة ، والبيانات الي حصلت بعدها ناخدها من الـ AOF. ولكن لو فيه تضارب بين محتويات RDB و AOF (وده نادر)، يفضّل نستعمل الـ AOF ونعتمد عليه لوحده، لأنه أحدث.
في الختام
في النهاية، Redis بتوفرلنا مرونة كبيرة في التعامل مع حفظ البيانات، واحنا اللي بنقرر أنهي طريقة تناسب شغلنا على حسب احتياجاتنا. المهم إننا نبقى فاهمين إزاي Redis بتخزن البيانات، وإزاي نختار الإعدادات اللي تحمينا من المفاجآت.
Discussion