عميل Redis للغة Go (Golang): go-redis و redigo
\n\nRedis هو مخزن بيانات عالي الأداء في الذاكرة (in-memory)، يُستخدم غالبًا كقاعدة بيانات وذاكرة تخزين مؤقت ووسيط للرسائل. للعمل مع Redis بلغة Go (Golang)، توجد عدة عملاء شائعون. في هذه المقالة، سنستعرض بالتفصيل مكتبتين رئيسيتين: go-redis (الخيار الأكثر شيوعًا وحداثة) و redigo (الأقل مستوى ولكن المختبر عبر الزمن).
\n\nسنوضح كيفية تثبيت كل منهما، والاتصال بالخادم، وتنفيذ العمليات الأساسية، والعمل مع تجمع الاتصالات، واستخدام pub/sub والمعالجة الأنبوبية (pipeline). ستكون المادة مفيدة لكل من المبتدئين والمطورين ذوي الخبرة الذين يرغبون في دمج Redis في تطبيقات Go الخاصة بهم.
\n\n1. go-redis — عميل حديث ووظيفي
\n\ngo-redis هي مكتبة عميل لـ Redis مكتوبة بلغة Go. تدعم جميع الميزات الرئيسية لـ Redis 6 و 7، بما في ذلك التجميع (clustering) و Sentinel و pub/sub والمعاملات و pipeline ونصوص Lua. المكتبة قيد التطوير النشط ولها واجهة برمجة تطبيقات (API) مريحة.
\n\nتثبيت go-redis
\nللتثبيت، قم بتنفيذ الأمر التالي في الطرفية:
\ngo get github.com/redis/go-redis/v9\n\nالاتصال والعمليات الأساسية
\nمثال لتطبيق بسيط يتصل بـ Redis، ويكتب ويقرأ البيانات:
\npackage main\n\nimport (\n "context"\n "fmt"\n "github.com/redis/go-redis/v9"\n)\n\nfunc main() {\n ctx := context.Background()\n\n // إنشاء عميل\n rdb := redis.NewClient(&redis.Options{\n Addr: "localhost:6379",\n Password: "", // بدون كلمة مرور\n DB: 0, // قاعدة البيانات الافتراضية\n })\n\n // التحقق من الاتصال\n pong, err := rdb.Ping(ctx).Result()\n if err != nil {\n panic(err)\n }\n fmt.Println(pong) // PONG\n\n // كتابة قيمة\n err = rdb.Set(ctx, "key", "hello from Go", 0).Err()\n if err != nil {\n panic(err)\n }\n\n // قراءة القيمة\n val, err := rdb.Get(ctx, "key").Result()\n if err != nil {\n panic(err)\n }\n fmt.Println("key:", val)\n}\n\nالعمل مع التجزئات (Hashes) والقوائم (Lists) والمجموعات (Sets)
\nيدعم go-redis جميع أنواع بيانات Redis. مثال على العمل مع التجزئة (hash):
\n// كتابة تجزئة\nerr := rdb.HSet(ctx, "user:1000", map[string]interface{}{\n "name": "Alice",\n "age": 30,\n "city": "Moscow",\n}).Err()\nif err != nil {\n panic(err)\n}\n\n// قراءة حقل واحد\nname, err := rdb.HGet(ctx, "user:1000", "name").Result()\nfmt.Println("Name:", name)\n\n// قراءة التجزئة بأكملها\nuser, err := rdb.HGetAll(ctx, "user:1000").Result()\nfmt.Println("User:", user)\n\nتجمع الاتصالات والتكوين
\nيدير go-redis تجمع الاتصالات تلقائيًا. يمكنك ضبط حجمه:
\nrdb := redis.NewClient(&redis.Options{\n Addr: "localhost:6379",\n PoolSize: 10, // الحد الأقصى لعدد الاتصالات في التجمع\n MinIdleConns: 3, // الحد الأدنى لعدد الاتصالات الخاملة\n})\n\nPub/Sub (الناشر-المشترك)
\nمثال على الاشتراك في قناة ونشر رسالة:
\n// الاشتراك\nsub := rdb.Subscribe(ctx, "mychannel")\nch := sub.Channel()\n\n// في غوروتين منفصلة، نستمع للرسائل\ngo func() {\n for msg := range ch {\n fmt.Printf("Received: %s from %s\\n", msg.Payload, msg.Channel)\n }\n}()\n\n// النشر\nerr := rdb.Publish(ctx, "mychannel", "Hello subscribers!").Err()\n\nPipeline (الأنبوب)
\nيسمح بإرسال عدة أوامر في طلب واحد، مما يسرع العمل بشكل كبير:
\npipe := rdb.Pipeline()\n\nincr := pipe.Incr(ctx, "counter")\npipe.Expire(ctx, "counter", time.Hour)\n\n// تنفيذ جميع الأوامر\n_, err := pipe.Exec(ctx)\nif err != nil {\n panic(err)\n}\nfmt.Println("Counter:", incr.Val())\n\n