تجزئات Redis (الجزء 2)
يغطي هذا الدرس العمليات الرقمية على حقول التجزئة والاستعلامات التكرارية والميزات المتقدمة الأخرى.
HINCRBY: زيادة قيم الحقول
يمكن لحقول التجزئة تخزين سلاسل رقمية ودعم العمليات الحسابية الذرية.
HINCRBY: زيادة عدد صحيح
REDIS
# إنشاء إحصاءات المقالة
HSET article:123 views 1000 likes 50 comments 20
# زيادة عدد المشاهدات
HINCRBY article:123 views 1
(integer) 1001
# زيادة عدد الإعجابات
HINCRBY article:123 likes 1
(integer) 51
# زيادة دفعات
HINCRBY article:123 views 10
(integer) 1011
# إنقاص (تمرير رقم سالب)
HINCRBY article:123 likes -1
(integer) 50
HINCRBYFLOAT: زيادة عدد عائم
REDIS
# سعر المنتج
HSET product:2001 price 99.99
# زيادة السعر
HINCRBYFLOAT product:2001 price 10.5
"110.49"
# إنقاص السعر (تمرير رقم سالب)
HINCRBYFLOAT product:2001 price -5.0
"105.49"
حالة الاستخدام: مجموعة عدادات
REDIS
# إحصاءات المستخدم
HSET user:stats:1 posts 0 followers 0 following 0
# نشر مقالة
HINCRBY user:stats:1 posts 1
# كسب متابع
HINCRBY user:stats:1 followers 1
# متابعة شخص
HINCRBY user:stats:1 following 1
# عرض الإحصاءات
HGETALL user:stats:1
💡 الميزة: استخدام تجزئة لتخزين عدادات متعددة أكثر كفاءة في الذاكرة من استخدام مفاتيح سلاسل متعددة.
HSCAN: التكرار عبر التجزئات الكبيرة
عندما تحتوي التجزئة على حقول كثيرة، يُرجع HGETALL جميع البيانات مرة واحدة، مما قد يحظر الخادم. HSCAN يسمح بالتكرار على دفعات.
الاستخدام الأساسي
REDIS
# إنشاء تجزئة كبيرة
HSET large:hash field1 "value1" field2 "value2" ... field1000 "value1000"
# بدء التكرار
HSCAN large:hash 0
1) "127" # مؤشر للتكرار التالي
2) 1) "field1"
2) "value1"
3) "field2"
4) "value2"
...
# متابعة التكرار
HSCAN large:hash 127
1) "0" # مؤشر 0 يعني اكتمال التكرار
2) 1) "field999"
2) "value999"
...
نمط المطابقة
REDIS
# الحصول فقط على الحقول المطابقة لنمط
HSCAN user:1 0 MATCH age*
1) "0"
2) 1) "age"
2) "25"
تحديد العدد لكل تكرار
REDIS
# إرجاع حوالي 100 حقل لكل تكرار
HSCAN large:hash 0 COUNT 100
💡 حالة الاستخدام: HSCAN رائع للتكرار عبر التجزئات الكبيرة دون حظر الخادم.
تطبيقات التجزئة المتقدمة
حالة الاستخدام 1: تفاصيل منتج التجارة الإلكترونية
REDIS
# تخزين معلومات المنتج الكاملة
HSET product:3001 \
name "iPhone 15 Pro" \
brand "Apple" \
price 8999 \
stock 100 \
category "phone" \
sales 0 \
rating 4.8
# عرض معلومات المنتج الأساسية
HMGET product:3001 name price stock
# زيادة المبيعات
HINCRBY product:3001 sales 1
# إنقاص المخزون
HINCRBY product:3001 stock -1
# تحديث التقييم
HSET product:3001 rating 4.9
# التحقق من المخزون
HGET product:3001 stock
حالة الاستخدام 2: إعدادات المستخدم
REDIS
# تخزين إعدادات المستخدم
HSET user:config:1 \
theme "dark" \
language "en" \
notifications "on" \
privacy "public" \
timezone "America/New_York"
# الحصول على إعداد واحد
HGET user:config:1 theme
# تعديل إعداد
HSET user:config:1 theme "light"
# الحصول على إعدادات دفعات
HMGET user:config:1 theme language notifications
حالة الاستخدام 3: إحصاءات فورية
REDIS
# إحصاءات الموقع اليومية
HSET stats:20260623 \
page_views 0 \
unique_visitors 0 \
new_users 0 \
orders 0 \
revenue 0.0
# زيادة مشاهدات الصفحة
HINCRBY stats:20260623 page_views 1
# زيادة الزوار الفريدين
HINCRBY stats:20260623 unique_visitors 1
# زيادة الطلبات
HINCRBY stats:20260623 orders 1
# زيادة الإيرادات
HINCRBYFLOAT stats:20260623 revenue 299.99
# عرض الإحصاءات
HGETALL stats:20260623
حالة الاستخدام 4: إعدادات اختبار A/B
REDIS
# تخزين إعدادات التجربة
HSET experiment:homepage \
button_color "blue" \
layout "grid" \
show_banner "yes" \
discount_rate 0.1
# الحصول على إعداد التجربة
HGET experiment:homepage button_color
# تحديث إعداد التجربة
HSET experiment:homepage button_color "red"
مقارنة Hash مع JSON
مقارنة التخزين
الطريقة 1: Hash
REDIS
HSET user:1 name "Alice" age 25 email "alice@example.com"
الطريقة 2: String JSON
REDIS
SET user:1 '{"name":"Alice","age":25,"email":"alice@example.com"}'
مقارنة العمليات
| العملية | Hash | String JSON |
|---|---|---|
| الحصول على حقل واحد | HGET user:1 name |
يحتاج تحليل JSON |
| تعديل حقل واحد | HSET user:1 age 26 |
قراءة → تحليل → تعديل → تسلسل → كتابة |
| الحصول على جميع الحقول | HGETALL user:1 |
GET user:1 + تحليل JSON |
| عملية رقمية | HINCRBY user:1 age 1 |
يحتاج تحليل → تعديل → تسلسل |
| استخدام الذاكرة | أصغر | أكبر (ترميز JSON زائد) |
مقارنة حالات الاستخدام
| السيناريو | الموصى به | السبب |
|---|---|---|
| ملف المستخدم | Hash | حقول مستقلة، تحديثات متكررة |
| معلومات المنتج | Hash | حقول مستقلة، تحديثات جزئية |
| كائنات متداخلة معقدة | String JSON | Hash لا يدعم التداخل |
| بيانات مصفوفة | String JSON | Hash لا يدعم المصفوفات |
| كائن إعدادات | Hash | حقول مستقلة، استعلامات سريعة |
💡 مبدأ الاختيار:
- حقول مستقلة، تحديثات جزئية متكررة → Hash
- تداخل معقد، مصفوفات مطلوبة → String JSON
- عمليات رقمية مطلوبة → Hash
تحسين الأداء
1. تجنب التجزئات الكبيرة
REDIS
# ❌ غير موصى به: تجزئة واحدة مع عدد كبير جدًا من الحقول
HSET big:hash field1 ... field10000
# ✅ موصى به: تقسيم إلى تجزئات متعددة
HSET hash:part1 field1 ... field1000
HSET hash:part2 field1001 ... field2000
2. استخدام HSCAN بدلاً من HGETALL
REDIS
# ❌ HGETALL على تجزئة كبيرة
HGETALL large:hash # قد يحظر
# ✅ استخدم HSCAN للتكرار
HSCAN large:hash 0
3. العمليات الدفعية تقلل جولات الشبكة
REDIS
# ❌ عمليات فردية متعددة
HSET user:1 name "Alice"
HSET user:1 age 25
HSET user:1 city "Beijing"
# ✅ عملية دفعات
HSET user:1 name "Alice" age 25 city "Beijing"
4. تكوين عتبات الترميز
في redis.conf:
CONF
# عتبة عدد حقول التجزئة (الافتراضي 512)
hash-max-ziplist-entries 512
# الحد الأقصى لطول قيمة حقل التجزئة (الافتراضي 64 بايت)
hash-max-ziplist-value 64
ℹ️ ملاحظة: زيادة العتبات يمكن أن توفر الذاكرة لكنها قد تقلل الأداء. اضبط بناءً على بياناتك الفعلية.
قيود التجزئة
1. عدم دعم التداخل
REDIS
# ❌ لا يمكن تخزين كائنات متداخلة مباشرة
HSET user:1 address '{"city":"Beijing","zip":"100000"}'
# ✅ استخدم سلسلة للأجزاء المتداخلة
HSET user:1 city "Beijing" zip "100000"
2. عدم دعم المصفوفات
REDIS
# ❌ لا يمكن تخزين مصفوفات
HSET user:1 tags ["redis","database","cache"]
# ✅ استخدم مجموعة أو قائمة للمصفوفات
SADD user:1:tags "redis" "database" "cache"
3. القيم يمكن أن تكون سلاسل فقط
REDIS
# جميع القيم هي سلاسل
HSET user:1 age 25
HGET user:1 age
"25" # يُرجع سلسلة، وليس عددًا صحيحًا
❓ أسئلة شائعة
س ماذا يحدث إذا تم استخدام HINCRBY على حقل غير رقمي؟
ج يُرجع خطأ:
(error) ERR hash value is not an integer. تأكد من أن قيمة الحقل هي سلسلة رقمية。س هل حقول التجزئة مرتبة؟
ج لا. حقول التجزئة غير مرتبة — HGETALL لا يضمن أي ترتيب محدد。
س كيف أتحقق مما إذا كان المفتاح من نوع تجزئة؟
ج استخدم أمر TYPE:
TYPE user:1 يُرجع hash。س هل يضمن HSCAN عدم وجود تكرار؟
ج لا. قد يُرجع HSCAN حقولًا مكررة — يجب على طبقة التطبيق التعامل مع إزالة التكرار。
س ما الفرق بين التجزئة والمجموعة؟
ج التجزئة تخزن أزواج حقل-قيمة؛ المجموعة تخزن عناصر فريدة. التجزئات للكائنات، المجموعات للعلامات والعلاقات。
📖 ملخص
- HINCRBY/HINCRBYFLOAT تؤدي عمليات رقمية على الحقول
- HSCAN يتكرر عبر التجزئات الكبيرة، متجنبًا الحظر
- التجزئات مناسبة للمنتجات والإعدادات وكائنات الإحصاءات
- Hash مقابل String JSON: Hash للكائنات البسيطة مع تحديثات جزئية
- نصائح الأداء: تجنب التجزئات الكبيرة، استخدم HSCAN، العمليات الدفعية
- قيود التجزئة: لا تدعم التداخل، لا تدعم المصفوفات، القيم سلاسل فقط
📝 تمارين
- العمليات الرقمية: استخدم تجزئة لتخزين إحصاءات المقالة (مشاهدات، إعجابات، تعليقات) وقم بالزيادة باستخدام HINCRBY
- إدارة المنتجات: استخدم تجزئة لتخزين معلومات المنتج، تدرب على العرض والتعديل وزيادة المبيعات وإنقاص المخزون
- إدارة الإعدادات: استخدم تجزئة لإعدادات المستخدم، تدرب على الحصول على إعداد واحد وإعدادات دفعات وتعديل الإعدادات
- مقارنة الأداء: قارن خطوات تعديل حقل واحد باستخدام Hash مقابل String JSON
الدرس التالي
في الدرس التالي، سنتعلم قوائم Redis (الجزء 1)، والتي تغطي عمليات القوائم الأساسية.



