التخزين المؤقت في Go: Redis وMemcached والحلول المدمجة (مستوى متقدم)

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

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

ابدأ الدورة

مقدمة: لماذا نحتاج إلى التخزين المؤقت في Go على المستوى المتقدم؟

\n\n

في الأنظمة عالية التحميل بلغة Go (Golang)، غالبًا ما تصبح سرعة الوصول إلى البيانات عنق الزجاجة. قاعدة البيانات ليست دائمًا قادرة على معالجة آلاف الطلبات في الثانية دون تأخيرات كبيرة. التخزين المؤقت هو أداة رئيسية لتقليل الحمل على قاعدة البيانات وتسريع استجابة API.

\n\n

على المستوى المبتدئ، غالبًا ما يستخدم المطورون map بسيطة مع أقفال (mutexes). ومع ذلك، في بيئة الإنتاج، هناك حاجة إلى حلول أكثر تقدمًا: التخزين المؤقت الموزع (Redis، Memcached) ومكتبات in-memory عالية الأداء (BigCache، FreeCache). في هذه المقالة، سنشرح ميزاتها، ونقارن أداءها، ونعرض أمثلة على الكود بلغة Go لكل خيار.

\n\n

1. الحلول المدمجة: sync.Map ومكتبات BigCache/FreeCache

\n\n

1.1. sync.Map - عندما لا تحتاج إلى تبعية خارجية

\n\n

حزمة sync.Map هي map آمنة للخيوط، محسنة للسيناريوهات التي يتم فيها كتابة المفاتيح مرة واحدة وقراءتها عدة مرات. لا تتطلب أقفالًا للقراءة، مما يعطي زيادة في الأداء.

\n\n

مثال على الاستخدام:

\n
package main\n\nimport (\n    "fmt"\n    "sync"\n)\n\nfunc main() {\n    var cache sync.Map\n\n    // كتابة\n    cache.Store("user:1", "Alice")\n\n    // قراءة\n    if value, ok := cache.Load("user:1"); ok {\n        fmt.Println("تم العثور على:", value)\n    }\n\n    // حذف\n    cache.Delete("user:1")\n}
\n\n

العيوب: لا يوجد إبطال تلقائي بناءً على TTL، ولا يوجد حد للذاكرة. مناسب للتخزين المؤقت المؤقت للتكوينات أو البيانات نادرة التغيير.

\n\n

1.2. BigCache - تخزين مؤقت سريع in-memory مع TTL

\n\n

BigCache من Allegro هي مكتبة تخزن البيانات في مصفوفات بايت، متجنبة النفقات العامة لـ GC. تدعم TTL والإخلاء التلقائي للسجلات القديمة.

\n\n

مثال:

\n
import (\n    "github.com/allegro/bigcache/v3"\n    "time"\n)\n\nfunc main() {\n    cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(10 * time.Minute))\n\n    // كتابة\n    cache.Set("mykey", []byte("myvalue"))\n\n    // قراءة\n    entry, _ := cache.Get("mykey")\n    println(string(entry))\n}
\n\n

المزايا: ضغط ضئيل على GC، سرعة عالية (ملايين العمليات في الثانية). العيوب: يتم تخزين البيانات فقط بالبايت، لا يوجد دعم للهياكل المعقدة بدون تسلسل.

\n\n

1.3. FreeCache - بديل بحجم ثابت

\n\n

FreeCache هي مكتبة in-memory أخرى بحجم تخزين مؤقت قابل للتخصيص. تستخدم التقسيم (segmentation) لتقليل الأقفال.

\n\n
import "github.com/coocood/freecache"\n\nfunc main() {\n    // حجم التخزين المؤقت - 100 ميجابايت\n    cache := freecache.NewCache(100 * 1024 * 1024)\n\n    cache.Set([]byte("key"), []byte("value"), 60) // TTL 60 ثانية\n    got, _ := cache.Get([]byte("key"))\n    println(string(got))\n}
\n\n

2. Redis - التخزين المؤقت الموزع مع هياكل متقدمة

\n\n

Redis هو التخزين المؤقت الخارجي الأكثر شيوعًا لتطبيقات Go. لا يدعم السلاسل النصية فحسب، بل يدعم أيضًا القوائم والتجزئات والمجموعات، بالإضافة إلى TTL وPub/Sub والمعاملات.

\n\n

2.1. الاتصال والعمليات الأساسية

\n\n

للعمل مع Redis في Go، يتم استخدام برنامج التشغيل go-redis/redis (أو redis/v8).

\n\n
import (\n    "github.com/go-redis/redis/v8"\n    "context"\n)\n\nvar ctx = context.Background()\n\nfunc main() {\n    rdb := redis.NewClient(&redis.Options{\n        Addr:     "localhost:6379",\n        Password: "",\n        DB:       0,\n    })\n\n    // تعيين مع TTL لمدة 10 ثوانٍ\n    err := rdb.Set(ctx, "key", "value", 10*time.Second).Err()\n    if err != nil {\n        panic(err)\n    }\n\n    val, err := rdb.Get(c                

المدونات

توصيات الكتب