التخزين المؤقت في C++: Redis وMemcached والحلول المدمجة — المستوى المتقدم

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا التخزين المؤقت ضروري لأداء C++

\n

في التطوير الحديث عالي التحميل بلغة C++، لم يعد التخزين المؤقت خيارًا - بل أصبح عنصرًا إلزاميًا في البنية. بدونه، أي نظام CRUD أو خدمة مصغرة ستواجه بسرعة حدود قاعدة البيانات، وستنمو زمن الاستجابة للطلبات بشكل أسي. على المستوى المتقدم، نواجه معضلة: استخدام أنظمة خارجية (Redis، Memcached) أو نشر حل تخزين مؤقت خاص في الذاكرة بلغة C++؟ في هذه المقالة، سنحلل الإيجابيات والسلبيات والتنفيذات المحددة لكل نهج، بناءً على ممارسة العمل مع قوائم انتظار الشبكة، والأقفال، والتسلسل.

\n\n

1. Redis: المرونة وهياكل البيانات

\n

Redis ليس مجرد مخزن key-value. ميزته الرئيسية هي مجموعة غنية من أنواع البيانات: السلاسل، التجزئات، القوائم، المجموعات، المجموعات المرتبة. بالنسبة لـ C++، هناك عدة عملاء: redis-plus-plus (موصى به) و hiredis (مستوى منخفض).

\n

مثال على الاتصال والعمليات الأساسية مع redis-plus-plus

\n
#include <sw/redis++/redis++.h>\n#include <iostream>\n\nint main() {\n    // الاتصال بـ Redis (افتراضيًا localhost:6379)\n    sw::redis::Redis redis("tcp://127.0.0.1:6379");\n\n    // تعيين قيمة مع TTL لمدة 60 ثانية\n    redis.set("user:1001", "John Doe", std::chrono::seconds(60));\n\n    // القراءة\n    auto val = redis.get("user:1001");\n    if (val) {\n        std::cout << "User: " << *val << std::endl;\n    }\n\n    // العمل مع التجزئات\n    redis.hset("session:abc", "token", "xyz123");\n    redis.hset("session:abc", "expires", "3600");\n    auto token = redis.hget("session:abc", "token");\n    std::cout << "Token: " << *token << std::endl;\n\n    return 0;\n}\n
\n

ميزات متقدمة: استخدام المعاملات عبر redis.multi() و redis.exec()، بالإضافة إلى Pub/Sub للإشعارات بإبطال التخزين المؤقت. Redis مناسب تمامًا عندما تحتاج إلى تخزين هياكل معقدة مع عمليات ذرية (مثل زيادة العداد).

\n\n

2. Memcached: السرعة والبساطة

\n

Memcached هو كاش موزع خفيف الوزن، محسّن لتخزين البيانات المسطحة (السلاسل والكتل الثنائية). لا يدعم المعاملات أو الهياكل المعقدة، لكنه يتفوق في السرعة والاستهلاك الأدنى للذاكرة. بالنسبة لـ C++، نستخدم مكتبة libmemcached.

\n

مثال على العمل مع Memcached عبر libmemcached

\n
#include <libmemcached/memcached.h>\n#include <iostream>\n#include <cstring>\n\nint main() {\n    memcached_st *memc = memcached_create(nullptr);\n    memcached_server_st *servers = nullptr;\n    memcached_return_t rc;\n\n    // إضافة خادم\n    servers = memcached_server_list_append(servers, "127.0.0.1", 11211, &rc);\n    rc = memcached_server_push(memc, servers);\n    if (rc != MEMCACHED_SUCCESS) {\n        std::cerr << "Error: " << memcached_strerror(memc, rc) << std::endl;\n        return 1;\n    }\n\n    // كتابة مع TTL لمدة 30 ثانية\n    const char *key = "config:db_host";\n    const char *value = "10.0.0.1";\n    rc = memcached_set(memc, key, strlen(key), value, strlen(value), \n                       std::time(0) + 30, (uint32_t)0);\n    if (rc != MEMCACHED_SUCCESS) {\n        std::cerr << "Set failed: " << memcached_strerror(memc, rc) << std::endl;\n    }\n\n    // القراءة\n    size_t val_len;\n    uint32_t flags;\n    char *retrieved = memcached_get(memc, key, strlen(key), &val_len, &flags, &rc);\n    if (rc == MEMCACHED_SUCCESS) {\n        std::cout << "DB Host: " << retrieved << std::endl;\n        free(retrieved);\n    }\n\n    memcached_free(memc);\n    return 0;\n}\n
\n

متى تختار Memcached؟ إذا كنت بحاجة إلى كاش بسيط للكائنات المسلسلة، دون الحاجة إلى تخزين هياكل معقدة. Memcached مثالي لتخزين نتائج استعلامات SQL أو أجزاء HTML مؤقتًا.

المدونات

توصيات الكتب