تجزئات 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 حقولًا مكررة — يجب على طبقة التطبيق التعامل مع إزالة التكرار。
س ما الفرق بين التجزئة والمجموعة؟
ج التجزئة تخزن أزواج حقل-قيمة؛ المجموعة تخزن عناصر فريدة. التجزئات للكائنات، المجموعات للعلامات والعلاقات。

📖 ملخص

📝 تمارين

  1. العمليات الرقمية: استخدم تجزئة لتخزين إحصاءات المقالة (مشاهدات، إعجابات، تعليقات) وقم بالزيادة باستخدام HINCRBY
  2. إدارة المنتجات: استخدم تجزئة لتخزين معلومات المنتج، تدرب على العرض والتعديل وزيادة المبيعات وإنقاص المخزون
  3. إدارة الإعدادات: استخدم تجزئة لإعدادات المستخدم، تدرب على الحصول على إعداد واحد وإعدادات دفعات وتعديل الإعدادات
  4. مقارنة الأداء: قارن خطوات تعديل حقل واحد باستخدام Hash مقابل String JSON

الدرس التالي

في الدرس التالي، سنتعلم قوائم Redis (الجزء 1)، والتي تغطي عمليات القوائم الأساسية.

100%