Redis
Redis هو قاعدة بيانات مفتوحة المصدر لتخزين أزواج المفتاح-القيمة (Key-Value)، مكتوبة بلغة ANSI C، وتلتزم ببروتوكول BSD، وتدعم الشبكة، ويمكن أن تعتمد على الذاكرة، وموزعة، مع إمكانية الاستمرارية الاختيارية، وتوفر واجهات برمجة تطبيقات بلغات متعددة. يمكن استخدام Redis كقاعدة بيانات NoSQL، أو كذاكرة تخزين مؤقت عالية السرعة، كما يدعم قوائم انتظار الرسائل البسيطة.
تشرح هذه المقالة فقط كيفية استخدام مشغل لغة Go للتعامل مع قاعدة بيانات Redis، ولن تشرح Redis نفسه بأي شكل.
الوثائق الرسمية: Golang Redis client (uptrace.dev)
المستودع الرسمي: go-redis/redis: Type-safe Redis client for Golang (github.com)
التثبيت
هناك العديد من المشغلات الخاصة بـ Redis، وتستخدم هذه المقالة github.com/go-redis/redis.
إذا كنت تستخدم Redis نسخة 6
go get github.com/go-redis/redis/v8إذا كنت تستخدم Redis نسخة 7
go get github.com/go-redis/redis/v9البدء السريع
import (
"fmt"
"log"
"testing"
"github.com/go-redis/redis"
)
func TestQuickStart(t *testing.T) {
// إنشاء عميل اتصال Redis
redisClient := redis.NewClient(&redis.Options{
Addr: "192.168.48.134:6379",
Password: "123456",
DB: 0, // استخدام قاعدة البيانات الافتراضية
})
// تعيين زوج مفتاح-قيمة، 0 يعني عدم انتهاء الصلاحية أبدًا
redisClient.Set("hello", "world", 0)
// قراءة القيمة
result, err := redisClient.Get("hello").Result()
if err == redis.Nil {
fmt.Println("ket not exist")
} else if err != nil {
log.Panic(err)
}
fmt.Println(result)
}إعدادات الاتصال
type Options struct {
// نوع الشبكة tcp أو unix.
// الافتراضي هو tcp.
Network string
// عنوان redis، التنسيق host:port
Addr string
// Dialer ينشئ اتصال شبكة جديد وله أولوية أعلى من Network و Addr
// Network and Addr options.
Dialer func() (net.Conn, error)
// عند إنشاء اتصال redis جديد، يتم استدعاء هذه الدالة
OnConnect func(*Conn) error
// كلمة مرور redis، يمكن أن تكون فارغة إذا لم يكن خادم redis قد حددها.
Password string
// قاعدة بيانات redis، الترقيم يبدأ من 0، الافتراضي هو 0، يمكن عدم تعيينه
DB int
// الحد الأقصى لعدد مرات إعادة المحاولة عند فشل عملية redis، الافتراضي 0.
MaxRetries int
// الحد الأدنى للفاصل الزمني لإعادة المحاولة.
// الافتراضي هو 8ms ; -1 يعني التعطيل.
MinRetryBackoff time.Duration
// الحد الأقصى للفاصل الزمني لإعادة المحاولة
// الافتراضي هو 512ms; -1 يعني التعطيل.
MaxRetryBackoff time.Duration
// مهلة إنشاء اتصال redis جديد.
// الافتراضي هو 5 ثوان.
DialTimeout time.Duration
// مهلة قراءة socket
// الافتراضي 3 ثوان.
ReadTimeout time.Duration
// مهلة الكتابة على socket
WriteTimeout time.Duration
// الحد الأقصى لعدد الاتصالات في تجمّع اتصالات redis.
// الافتراضي حجم تجمّع الاتصالات يساوي عدد المعالجات * 10
PoolSize int
// الحد الأدنى لعدد الاتصالات الخاملة في تجمّع اتصالات redis.
MinIdleConns int
// الحد الأقصى لوقت بقاء اتصال redis، الافتراضي لا يتم إغلاق الاتصالات القديمة.
MaxConnAge time.Duration
// بعد الحصول على اتصال من تجمّع اتصالات redis، كم من الوقت ينتظر تجمّع الاتصالات للاتصال المأخوذ.
// الافتراضي هو انتظار ReadTimeout + 1 ثانية.
PoolTimeout time.Duration
// كم من الوقت يغلق تجمّع اتصالات redis اتصالًا خاملًا.
// الافتراضي هو 5 دقائق. -1 يعني تعطيل هذا الخيار
IdleTimeout time.Duration
// كم من الوقت للتحقق من الاتصالات الخاملة
// الافتراضي هو 1 دقيقة. -1 يعني تعطيل التحقق من الاتصالات الخاملة
IdleCheckFrequency time.Duration
// إعداد القراءة فقط، إذا تم ضبطه على true، في مثيل العقدة الحالية، redis يمكنه فقط الاستعلام عن التخزين المؤقت ولا يمكنه التحديث.
readOnly bool
// إعدادات TLS
TLSConfig *tls.Config
}إنشاء الاتصال
// إنشاء عميل اتصال Redis
redisClient := redis.NewClient(&redis.Options{
Addr: "192.168.48.134:6379",
Password: "123456",
DB: 0, // استخدام قاعدة البيانات الافتراضية
})إغلاق الاتصال
المشغل يحافظ على تجمّع اتصالات داخليًا، لا حاجة لإغلاق الاتصال بعد كل عملية.
defer redisClient.Close()هذا المشغل لـ Redis قام بتغليف جميع العمليات تقريبًا، أوامر Redis وأسماء الدوال متطابقة واحد لواحد، في الأساس إذا عرفت كيفية استخدام أوامر Redis، فستعرف تقريبًا كيفية استخدام الدوال المقابلة في المشغل.
أوامر Redis: دليل أوامر redis
العمليات الأساسية
حذف المفتاح
redisClient.Set("name", "jack", 0)
fmt.Println(redisClient.Del("name").Result())وقت انتهاء الصلاحية
redisClient.Set("name", "jack", 0)
// تعيين وقت انتهاء الصلاحية
redisClient.Expire("name", time.Second*2)
fmt.Println(redisClient.Get("name").Val())
time.Sleep(time.Second * 3)
fmt.Println(redisClient.Get("name").Val())إلغاء وقت انتهاء الصلاحية
redisClient.Set("name", "jack", 2)
// إلغاء وقت انتهاء الصلاحية
redisClient.Persist("name")
time.Sleep(time.Second * 2)
fmt.Println(redisClient.Get("name"))الاستعلام عن وقت انتهاء الصلاحية
fmt.Println(redisClient.TTL("name"))
fmt.Println(redisClient.PTTL("name"))إعادة التسمية
redisClient.Rename("name", "newName")الاستعلام عن النوع
redisClient.Type("name")المسح
fmt.Println(redisClient.Scan(0, "", 4))السلاسل النصية
التخزين والاسترجاع البسيط
redisClient.Set("token", "abcefghijklmn", 0)
fmt.Println(redisClient.Get("token").Val())التخزين والاسترجاع المجمّع
redisClient.MSet("cookie", "12345", "token", "abcefg")
fmt.Println(redisClient.MGet("cookie", "token").Val())الزيادة والنقصان الرقمي
redisClient.Set("age", "1", 0)
// الزيادة التلقائية
redisClient.Incr("age")
fmt.Println(redisClient.Get("age").Val())
// النقصان التلقائي
redisClient.Decr("age")
fmt.Println(redisClient.Get("age").Val())جداول التجزئة
عمليات القراءة والكتابة
// تعيين فردي
redisClient.HSet("map", "name", "jack")
// تعيين مجموع
redisClient.HMSet("map", map[string]interface{}{"a": "b", "c": "d", "e": "f"})
// وصول فردي
fmt.Println(redisClient.HGet("map", "a").Val())
// وصول مجموع
fmt.Println(redisClient.HMGet("map", "a", "b").Val())
// الحصول على الخريطة بأكملها
fmt.Println(redisClient.HGetAll("map").Val())المخرجات
b
[b <nil>]
map[a:b c:d e:f name:jack]حذف المفتاح
// حذف حقل من الخريطة
redisClient.HDel("map", "a")التحقق من وجود المفتاح
// التحقق من وجود الحقل
redisClient.HExists("map", "a")الحصول على جميع المفاتيح
// الحصول على جميع مفاتيح الخريطة
redisClient.HKeys("map")الحصول على طول جدول التجزئة
// الحصول على طول الخريطة
redisClient.HLen("map")اجتياز أزواج المفتاح-القيمة في جدول التجزئة
// اجتياز أزواج المفتاح-القيمة في الخريطة
redisClient.HScan("map", 0, "", 1)القوائم
تعديل العناصر
// إضافة من اليسار
redisClient.LPush("list", "a", "b", "c", "d", "e")
// إضافة من اليمين
redisClient.RPush("list", "g", "i", "a")
// إدراج قيمة قبل القيمة المرجعية
redisClient.LInsertBefore("list", "a", "aa")
// إدراج قيمة بعد القيمة المرجعية
redisClient.LInsertAfter("list", "a", "gg")
// تعيين قيمة العنصر في الفهرس المحدد
redisClient.LSet("list", 0, "head")الوصول إلى الطول
// الوصول إلى طول القائمة
redisClient.LLen("list")الوصول إلى العناصر
// ظهور عنصر من اليسار
redisClient.LPop("list")
// ظهور عنصر من اليمين
redisClient.RPop("list")
// الوصول إلى العنصر في الفهرس المحدد
redisClient.LIndex("list", 1)
// الوصول إلى العناصر في النطاق المحدد
redisClient.LRange("list", 0, 1)حذف العناصر
// حذف عنصر محدد
redisClient.LRem("list", 0, "a")
// حذف عناصر في النطاق المحدد
redisClient.LTrim("list", 0, 1)
// الاحتفاظ بالعناصر في النطاق المحدد
redisClient.LTrim("list", 0, 1)المجموعات
إضافة عناصر
// إضافة عناصر إلى مجموعة
redisClient.SAdd("set", "a", "b", "c")
redisClient.SAdd("set2", "c", "d", "e")الوصول إلى عناصر المجموعة
// الحصول على جميع أعضاء المجموعة
redisClient.SMembers("set")
// التحقق مما إذا كان عنصر ينتمي إلى هذه المجموعة
redisClient.SIsMember("set", "a")
// إرجاع عدد محدد من العناصر عشوائيًا
redisClient.SRandMemberN("set", 1)
// الحصول على عدد عناصر المجموعة
redisClient.SCard("set")عمليات المجموعات
// إرجاع الفرق بين المجموعات المعطاة
redisClient.SDiff("set", "set2")
// حفظ الفرق بين المجموعات المعطاة في مجموعة النتائج، وإرجاع طول مجموعة النتائج
redisClient.SDiffStore("store", "set", "se2")
// إرجاع تقاطع المجموعات المعطاة
redisClient.SInter("set", "set2")
// حفظ تقاطع المجموعات المعطاة في مجموعة النتائج، وإرجاع طول مجموعة النتائج
redisClient.SInterStore("store", "set", "set2")
// إرجاع اتحاد المجموعات المعطاة
redisClient.SUnion("set", "set2")
// حفظ اتحاد المجموعات المعطاة في مجموعة النتائج، وإرجاع طول مجموعة النتائج
redisClient.SUnionStore("store", "set", "store")حذف العناصر
// ظهور وحذف العنصر
redisClient.SPop("set")
// ظهور وحذف N عنصر
redisClient.SPopN("set", 2)نقل العناصر
// نقل عنصر محدد من المجموعة المصدر إلى المجموعة الهدف
redisClient.SMove("set", "set2", "a")حذف العناصر
// حذف عنصر محدد
redisClient.SRem("set", "a", "b")الاجتياز
// اجتياز المجموعة
redisClient.SScan("set", 0, "", 2)المجموعات المرتبة
إضافة عناصر
// إضافة عناصر إلى المجموعة المرتبة
redisClient.ZAdd("ss", redis.Z{
Score: 1,
Member: "a",
}, redis.Z{
Score: 2,
Member: "b",
})ترتيب العناصر
// إرجاع ترتيب العنصر في المجموعة المرتبة، مرتبة من الأقل إلى الأعلى
redisClient.ZRank("ss", "1")
// إرجاع ترتيب العنصر في المجموعة المرتبة، مرتبة من الأعلى إلى الأقل
redisClient.ZRevRank("ss", "1")الوصول إلى العناصر
// إرجاع عدد الأعضاء بين min و max
redisClient.ZCount("ss", "1", "2")
// إرجاع وزن العنصر
redisClient.ZScore("ss", "a")
// إرجاع العناصر في النطاق المحدد
redisClient.ZRange("ss", 1, 2)
// إرجاع قائمة بجميع الأعضاء بين min و max
redisClient.ZRangeByScore("ss", redis.ZRangeBy{
Min: "1",
Max: "2",
Offset: 0,
Count: 1,
})تعديل الوزن
// زيادة الوزن المقابل لعنصر معين
redisClient.ZIncr("ss", redis.Z{
Score: 2,
Member: "b",
})حذف العناصر
// حذف عنصر محدد
redisClient.ZRem("ss", "a")
// حذف العناصر في نطاق ترتيب محدد
redisClient.ZRemRangeByRank("ss", 1, 2)
// حذف العناصر التي وزنها بين min و max
redisClient.ZRemRangeByScore("ss", "1", "2")البرمجة النصية
// تحميل النص البرمجي، إرجاع قيمة sha
redisClient.ScriptLoad("return 0")
// تنفيذ النص البرمجي بناءً على قيمة sha
redisClient.EvalSha("sha", []string{}, "")
// تنفيذ النص البرمجي مباشرة
redisClient.Eval("return 0", []string{}, "")
// مسح ذاكرة التخزين المؤقت للنصوص البرمجية
redisClient.ScriptFlush()
// إنهاء النص البرمجي قيد التشغيل حاليًا
redisClient.ScriptKill()
// التحقق مما إذا كان النص البرمجي بقيمة التجزئة المقابلة موجودًا
redisClient.ScriptExists("")النشر والاشتراك
// إرسال رسالة إلى قناة محددة
redisClient.Publish("channel", "message")
// الاشتراك في قناة محددة
redisClient.Subscribe("channel")
// عرض حالة الاشتراك
redisClient.PubSubNumSub("channel")