التفاعل مع Azure Cache for Redis باستخدام .NET

مكتمل

عادة ما يستخدم تطبيق العميل مكتبة عميل لتشكيل الطلبات وتنفيذ الأوامر على ذاكرة التخزين المؤقت Redis. يمكنك الحصول على قائمة بمكتبات العملاء مباشرةً من صفحة عملاء Redis.

تنفيذ الأوامر على ذاكرة التخزين المُؤقت لـ Redis

عميل Redis عالي الأداء الشهير للغة .NET هو StackExchange.Redis. تتوفر الحزمة من خلال NuGet ويمكن إضافتها إلى التعليمات البرمجية .NET باستخدام سطر الأوامر أو بيئة التطوير المتكامل (IDE). فيما يلي أمثلة حول كيفية استخدام العميل.

الاتصال بذاكرة التخزين المؤقت لـ Redis باستخدام StackExchange.Redis

تذكّر أننا نستخدم عنوان المضيف ورقم المنفذ ومفتاح الوصول للاتصال بخادم Redis. يقدم Azure أيضا سلسلة الاتصال لبعض عملاء Redis الذين يجمعون هذه البيانات معا في سلسلة واحدة. يبدو شيئا مثل ما يلي (مع cache-name الحقول و password-here مليئة بالقيم الحقيقية):

[cache-name].redis.cache.windows.net:6380,password=[password-here],ssl=True,abortConnect=False

يمكنك تمرير هذه السلسلة إلى StackExchange.Redis لإنشاء اتصال الخادم.

لاحظ أن هناك معلمتين إضافيتين في النهاية:

  • SSL- يضمن أن يتم تشفير الاتصالات.
  • abortConnection- يسمح بإنشاء اتصال حتى إذا كان الخادم غير متوفر في تلك اللحظة.

توجد العديد من المعلمات الاختيارية الأخرى التي يمكنك إلحاقها إلى السلسلة لتكوين مكتبة العميل.

إنشاء اتصال

عنصر الاتصال الرئيسي في StackExchange.Redis هو StackExchange.Redis.ConnectionMultiplexer الفئة. يلخص هذا العنصر عملية الاتصال إلى خادم Redis (أو مجموعة من الخوادم). تم تحسينه لإدارة الاتصالات بكفاءة بقصد الاحتفاظ به في أثناء الحاجة إلى الوصول إلى ذاكرة التخزين المؤقت.

تقوم بإنشاء ConnectionMultiplexer مثيل باستخدام ConnectionMultiplexer.Connect ثابت أوConnectionMultiplexer.ConnectAsync أسلوب تمرير في سلسلة اتصال أو ConfigurationOptionsعنصر.

إليك مثال بسيط:

using StackExchange.Redis;
...
var connectionString = "[cache-name].redis.cache.windows.net:6380,password=[password-here],ssl=True,abortConnect=False";
var redisConnection = ConnectionMultiplexer.Connect(connectionString);

بمجرد الحصول على ConnectionMultiplexer، توجد ثلاثة أمور أساسية قد ترغب في تنفيذها:

  • الوصول إلى قاعدة بيانات Redis. هذا ما سنركّز عليه هنا.
  • الاستفادة من ميزات الناشر/المشترك ل Redis. هذا خارج نطاق هذه الوحدة النمطية.
  • الوصول إلى خادم فردي من أجل الصيانة أو المراقبة.

الوصول إلى قاعدة بيانات Redis

يتم تمثيل قاعدة بيانات Redis وفقًا IDatabase للنوع. يمكنك إجراء استرداد واحد باستخدام GetDatabase() الأسلوب:

IDatabase db = redisConnection.GetDatabase();

تلميح

العنصر الذي تم إرجاعه من GetDatabase هو عنصر خفيف، ولا يحتاج إلى التخزين. يحتاج فقط ConnectionMultiplexer إلى أن يبقى حيًّا

بمجرد أن يكون لديك IDatabase عنصر، يمكنك تنفيذ أساليب التفاعل مع ذاكرة التخزين المُؤقت. تحتوي جميع الأساليب على إصدارات متزامنة وغير متزامنة تقوم بإرجاع Task الكائنات لجعلها متوافقة async مع الكلمات الأساسية و await .

فيما يلي مثال على تخزين مفتاح/قيمة في ذاكرة التخزين المؤقت:

bool wasSet = db.StringSet("favorite:flavor", "i-love-rocky-road");

يعمل StringSetالأسلوب على إرجاعbool والذي يشير إلى ما إذا كانت القيمة قد تم تعيينها (true) أم لا (false). يمكننا بعد ذلك استرداد القيمة مع StringGet الأسلوب:

string value = db.StringGet("favorite:flavor");
Console.WriteLine(value); // displays: ""i-love-rocky-road""

الحصول على القيم الثنائية وإعدادها

تذكّر أن مفاتيح Redis وقيمها آمنة ثنائيًا. يمكن استخدام تلك الأساليب ذاتها لتخزين البيانات الثنائية. توجد عوامل تحويل ضمنية للعمل مع byte[] الأنواع حتى تتمكن من العمل مع البيانات بشكل طبيعي:

byte[] key = ...;
byte[] value = ...;

db.StringSet(key, value);
byte[] key = ...;
byte[] value = db.StringGet(key);

يمثل StackExchange.Redis المفاتيح باستخدام RedisKey النوع. يوجد بهذه الفئة تحويلات ضمنية من وإلى string مع السماح لكل من النص والمفاتيح byte[] الثنائية باستخدامها دون أي تعقيد. تُمثّل القيم وفقًا للنوع RedisValue . كما هو الحال مع RedisKey، توجد تحويلات ضمنية في مكان يتيح لك تمرير string أو byte[].

العمليات الأخرى المشتركة

IDatabaseتتضمن الواجهة عدة أساليب أخرى للعمل مع ذاكرة التخزين المُؤقت لـ Redis. توجد أساليب للعمل مع التجزئة والقوائم والمجموعات وكذلك المجموعات المُرتبة.

نعرض فيما يلي البعض الأكثر شيوعًا منها، والذي يعمل مع مفاتيح واحدة، يمكنك قراءة التعليمات البرمجية للمصدر الخاص بالواجهة لرؤية القائمة الكاملة.

الطريقة ‏‏الوصف
CreateBatch إنشاء مجموعة من العمليات التي ستُرسل إلى الخادم في شكل وحدة واحدة، ولكن ليس بالضرورة معالجتها في شكل وحدة.
CreateTransaction إنشاء مجموعة من العمليات التي ستُرسل إلى الخادم في شكل وحدة واحدة ومعالجتها على الخادم في شكل وحدة واحدة.
KeyDelete حذف المفتاح/ القيمة.
KeyExists الإرجاع إذا كان المفتاح المُقدم موجودًا في ذاكرة التخزين المُؤقت.
KeyExpire تعيين مدة البقاء (TTL) الخاصة بانتهاء الصلاحية على أحد المفاتيح.
KeyRename إعادة تسمية المفتاح.
KeyTimeToLive إرجاع مدة البقاء (TTL) للمفتاح.
KeyType إرجاع تمثيل السلسلة من نوع القيمة المُخزنة في المفتاح. تشمل الأنواع المختلفة التي يمكن إرجاعها ما يلي: سلسلة وقائمة ومجموعة «zset» والتجزئة.

تنفيذ أوامر أخرى

IDatabase يحتوي الكائن على Execute أسلوب و ExecuteAsync الذي يمكن استخدامه لتمرير الأوامر النصية إلى خادم Redis. على سبيل المثال:

var result = db.Execute("ping");
Console.WriteLine(result.ToString()); // displays: "PONG"

ترجع Execute الأساليب و ExecuteAsync كائنا RedisResult هو صاحب بيانات يتضمن خاصيتين:

  • Type الذي يرجع string يشير إلى نوع النتيجة - "STRING" و"INTEGER" وما إلى ذلك.
  • IsNull قيمة صحيحة/ خاطئة للكشف عن متى تكون النتيجة null.

ومن ثم يمكنك استخدام ToString() للحصول على قيمة RedisResult الإرجاع الفعلي.

يمكنك استخدام Execute لتنفيذ أي أوامر مدعومة- على سبيل المثال، يمكننا الحصول على كل العملاء المتصلين بذاكرة التخزين المُؤقت ("قائمة العملاء"):

var result = await db.ExecuteAsync("client", "list");
Console.WriteLine($"Type = {result.Type}\r\nResult = {result}");

هذا مخرج للعملاء المتصلين:

Type = BulkString
Result = id=9469 addr=16.183.122.154:54961 fd=18 name=DESKTOP-AAAAAA age=0 idle=0 flags=N db=0 sub=1 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 ow=0 owmem=0 events=r cmd=subscribe numops=5
id=9470 addr=16.183.122.155:54967 fd=13 name=DESKTOP-BBBBBB age=0 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 ow=0 owmem=0 events=r cmd=client numops=17

تخزين قيم أكثر تعقيدًا

يُعد Redis موجهًا للسلاسل الآمنة الثنائية، ولكن يمكنك التخزين المُؤقت بعيدًا عن الرسوم البيانية للعنصر من خلال وضعهم في تسلسل من أجل تنسيق نصي - عادة XML أو JSON. على سبيل المثال، ربما بالنسبة لإحصائياتنا، لدينا كائن GameStats يبدو كما يلي:

public class GameStat
{
    public string Id { get; set; }
    public string Sport { get; set; }
    public DateTimeOffset DatePlayed { get; set; }
    public string Game { get; set; }
    public IReadOnlyList<string> Teams { get; set; }
    public IReadOnlyList<(string team, int score)> Results { get; set; }

    public GameStat(string sport, DateTimeOffset datePlayed, string game, string[] teams, IEnumerable<(string team, int score)> results)
    {
        Id = Guid.NewGuid().ToString();
        Sport = sport;
        DatePlayed = datePlayed;
        Game = game;
        Teams = teams.ToList();
        Results = results.ToList();
    }

    public override string ToString()
    {
        return $"{Sport} {Game} played on {DatePlayed.Date.ToShortDateString()} - " +
               $"{String.Join(',', Teams)}\r\n\t" + 
               $"{String.Join('\t', Results.Select(r => $"{r.team } - {r.score}\r\n"))}";
    }
}

يمكننا استخدام Newtonsoft.Jsعلى المكتبة لتشغيل مثيل هذا العنصر في سلسلة:

var stat = new GameStat("Soccer", new DateTime(2019, 7, 16), "Local Game", 
                new[] { "Team 1", "Team 2" },
                new[] { ("Team 1", 2), ("Team 2", 1) });

string serializedValue = Newtonsoft.Json.JsonConvert.SerializeObject(stat);
bool added = db.StringSet("event:1950-world-cup", serializedValue);

يمكننا استرداده وتحويله مرة أخرى إلى عنصر باستخدام عملية عكسية:

var result = db.StringGet("event:2019-local-game");
var stat = Newtonsoft.Json.JsonConvert.DeserializeObject<GameStat>(result.ToString());
Console.WriteLine(stat.Sport); // displays "Soccer"

تنظيف الاتصال

بمجرد الانتهاء من اتصال Redis، يمكنك DisposeConnectionMultiplexer. يؤدي ذلك إلى إغلاق كافة الاتصالات وإيقاف الاتصال بالخادم.

redisConnection.Dispose();
redisConnection = null;