التخزين المؤقت في C++: Redis وأدوات شائعة أخرى
في تطبيقات C++ ذات الأحمال العالية، سرعة الوصول إلى البيانات أمر بالغ الأهمية. يسمح التخزين المؤقت بتقليل زمن استجابة الخادم بمقدار 10 إلى 100 مرة، مما يقلل الحمل على قواعد البيانات وواجهات API الخارجية. في هذه المقالة، سنستعرض المكتبات الرئيسية للعمل مع التخزين المؤقت بلغة C++: من Redis الكلاسيكي إلى المحركات المضمنة LevelDB وRocksDB.
1. Redis ومكتبات العملاء للغة C++
Redis هو مخزن القيمة-المفتاح الأكثر شيوعًا في الذاكرة، ويدعم هياكل بيانات معقدة (قوائم، مجموعات، تجزئات). يوجد عميلان رئيسيان للغة C++:
- hiredis — مكتبة C بسيطة (رسمية)، يسهل دمجها في C++ من خلال أغلفة.
- redis-plus-plus — مكتبة C++17 حديثة مع تغطية كاملة لأوامر Redis، ودعم تجمع الاتصالات، وخط الأنابيب (pipeline)، والمعاملات.
مثال مع hiredis (متزامن)
#include <hiredis/hiredis.h>#include <iostream>
int main() { redisContext *c = redisConnect("127.0.0.1", 6379); if (c == nullptr || c->err) { std::cerr << "Connection error: " << c->errstr << std::endl; return 1; }
redisReply *reply = (redisReply*)redisCommand(c, "SET key hello"); freeReplyObject(reply);
reply = (redisReply*)redisCommand(c, "GET key"); if (reply->type == REDIS_REPLY_STRING) { std::cout << "GET key: " << reply->str << std::endl; } freeReplyObject(reply); redisFree(c); return 0;}مثال مع redis-plus-plus (غير متزامن + تجمع)
#include <sw/redis++/redis++.h>#include <iostream>
int main() { sw::redis::Redis redis("tcp://127.0.0.1:6379");
// تعيين مع TTL (5 ثوانٍ) redis.setex("user:42", 5, "John Doe");
// استرجاع auto val = redis.get("user:42"); if (val) { std::cout << "Cached user: " << *val << std::endl; } else { std::cout << "Key expired or not found" << std::endl; } return 0;}مزايا Redis: سرعة عالية (ميكروثانية)، مجموعة غنية من الأوامر، النسخ المتماثل، التجميع. العيوب: يستهلك ذاكرة الوصول العشوائي، ويتطلب خادمًا منفصلاً.
2. Memcached و libmemcached
Memcached — أبسط ذاكرة تخزين مؤقت موزعة، تخزن البيانات فقط في ذاكرة الوصول العشوائي. للغة C++، تُستخدم مكتبة libmemcached (أو غلافها C++ libmemcachedutil).
مثال مع libmemcached
#include <libmemcached/memcached.h>#include <iostream>#include <cstring>
int main() { memcached_st *memc = memcached_create(nullptr); memcached_server_add(memc, "127.0.0.1", 11211);
const char *key = "session_token"; const char *value = "abc123"; memcached_return_t rc = memcached_set(memc, key, strlen(key), value, strlen(value), 0, 0); // 0 - بدون ضغط، 0 - TTL
if (rc == MEMCACHED_SUCCESS) { size_t value_length; uint32_t flags; char *result = memcached_get(memc, key, strlen(key), &value_length, &flags, &rc); if (rc == MEMCACHED_SUCCESS) { std::cout << "Get: " << result << std::endl; free(result); } } memcached_free(memc); return 0;}متى تختار Memcached: إذا كنت بحاجة إلى تخزين مؤقت بسيط بدون هياكل بيانات معقدة، وكان الأداء الأقصى مهمًا. يتفوق Redis من حيث الوظائف، بينما يتفوق Memcached من حيث البساطة.
3. المحركات المضمنة: LevelDB و RocksDB
إذا كان يجب أن يكون التخزين المؤقت محليًا