البرنامج التعليمي: إنشاء ذاكرة تخزين مؤقت للكتابة في الخلف باستخدام Azure Functions وAzure Cache ل Redis

الهدف من هذا البرنامج التعليمي هو استخدام Azure Cache لمثيل Redis كذاكرة تخزين مؤقت للكتابة في الخلف. يوضح نمط الكتابة في الخلف في هذا البرنامج التعليمي كيفية الكتابة إلى مشغل ذاكرة التخزين المؤقت المقابلة للكتابات إلى قاعدة بيانات SQL (مثيل لخدمة قاعدة بيانات Azure SQL).

يمكنك استخدام مشغل Redis ل Azure Functions لتنفيذ هذه الوظيفة. في هذا السيناريو، سترى كيفية استخدام ذاكرة التخزين المؤقت Azure ل Redis لتخزين معلومات المخزون والتسعير، أثناء إجراء نسخ احتياطي لتلك المعلومات في قاعدة بيانات SQL.

ثم ينعكس كل عنصر جديد أو سعر جديد مكتوب إلى ذاكرة التخزين المؤقت في جدول SQL في قاعدة البيانات.

في هذا البرنامج التعليمي، تتعلم كيفية:

  • تكوين قاعدة بيانات ومشغل سلسلة الاتصال.
  • تحقق من أن المشغلات تعمل.
  • نشر التعليمات البرمجية إلى تطبيق دالة.

المتطلبات الأساسية

إنشاء قاعدة بيانات SQL جديدة وتكوينها

قاعدة بيانات SQL هي قاعدة بيانات الدعم لهذا المثال. يمكنك إنشاء قاعدة بيانات SQL من خلال مدخل Microsoft Azure أو من خلال أسلوب التشغيل التلقائي المفضل لديك.

لمزيد من المعلومات حول إنشاء قاعدة بيانات SQL، راجع التشغيل السريع: إنشاء قاعدة بيانات واحدة - قاعدة بيانات Azure SQL.

يستخدم هذا المثال المدخل:

  1. أدخل اسم قاعدة بيانات وحدد إنشاء جديد لإنشاء خادم جديد للاحتفاظ بقاعدة البيانات.

    لقطة شاشة لإنشاء مورد Azure SQL.

  2. حدد استخدام مصادقة SQL وأدخل تسجيل دخول المسؤول وكلمة المرور. تأكد من تذكر بيانات الاعتماد هذه أو كتابتها. عند نشر خادم في الإنتاج، استخدم مصادقة Microsoft Entra بدلا من ذلك.

    لقطة شاشة لمعلومات المصادقة لمورد Azure SQL.

  3. انتقل إلى علامة التبويب Networking واختر Public endpoint كطريقة اتصال. حدد نعم لكل من قواعد جدار الحماية التي تظهر. تسمح نقطة النهاية هذه بالوصول من تطبيق وظائف Azure.

    لقطة شاشة لإعداد الشبكة لمورد Azure SQL.

  4. بعد انتهاء التحقق من الصحة، حدد Review + create ثم Create. تبدأ قاعدة بيانات SQL في النشر.

  5. بعد انتهاء النشر، انتقل إلى المورد في مدخل Microsoft Azure وحدد علامة التبويب محرر الاستعلام. أنشئ جدولا جديدا يسمى المخزون الذي يحتوي على البيانات التي ستكتبها إليه. استخدم أمر SQL التالي لإنشاء جدول جديد مع حقلين:

    • ItemName يسرد اسم كل عنصر.
    • Price يخزن سعر العنصر.
    CREATE TABLE inventory (
        ItemName varchar(255),
        Price decimal(18,2)
        );
    

    لقطة شاشة تعرض إنشاء جدول في محرر Power Query لمورد Azure SQL.

  6. بعد انتهاء تشغيل الأمر، قم بتوسيع مجلد الجداول وتحقق من إنشاء الجدول الجديد.

تكوين مشغل Redis

أولا، قم بعمل نسخة من نفس مشروع VS Code الذي استخدمته في البرنامج التعليمي السابق. انسخ المجلد من البرنامج التعليمي السابق باسم جديد، مثل RedisWriteBehindTrigger، وافتحه في VS Code.

ثانيا، احذف ملفات RedisBindings.cs وملفات RedisTriggers.cs .

في هذا المثال، يمكنك استخدام مشغل pub/sub لتشغيل الإعلامات keyevent . أهداف المثال هي:

  • المشغل في SET كل مرة يحدث فيها حدث. SET يحدث حدث عند كتابة مفاتيح جديدة إلى مثيل ذاكرة التخزين المؤقت أو عند تغيير قيمة مفتاح.
  • SET بعد تشغيل حدث، قم بالوصول إلى مثيل ذاكرة التخزين المؤقت للعثور على قيمة المفتاح الجديد.
  • حدد ما إذا كان المفتاح موجودا بالفعل في جدول المخزون في قاعدة بيانات SQL.
    • إذا كان الأمر كذلك، فقم بتحديث قيمة هذا المفتاح.
    • إذا لم يكن الأمر كما هو، فاكتب صفا جديدا بالمفتاح وقيمته.

لتكوين المشغل:

  1. استيراد حزمة System.Data.SqlClient NuGet لتمكين الاتصال بقاعدة بيانات SQL. انتقل إلى محطة VS Code الطرفية واستخدم الأمر التالي:

      dotnet add package System.Data.SqlClient
    
  2. إنشاء ملف جديد يسمى RedisFunction.cs. تأكد من حذف ملفات RedisBindings.cs وملفات RedisTriggers.cs .

  3. انسخ التعليمات البرمجية التالية والصقها في RedisFunction.cs لاستبدال التعليمات البرمجية الموجودة:

using Microsoft.Extensions.Logging;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Extensions.Redis;
using System.Data.SqlClient;

public class WriteBehindDemo
{
    private readonly ILogger<WriteBehindDemo> logger;

    public WriteBehindDemo(ILogger<WriteBehindDemo> logger)
    {
        this.logger = logger;
    }
    
    public string SQLAddress = System.Environment.GetEnvironmentVariable("SQLConnectionString");

    //This example uses the PubSub trigger to listen to key events on the 'set' operation. A Redis Input binding is used to get the value of the key being set.
    [Function("WriteBehind")]
    public void WriteBehind(
        [RedisPubSubTrigger(Common.connectionString, "__keyevent@0__:set")] Common.ChannelMessage channelMessage,
        [RedisInput(Common.connectionString, "GET {Message}")] string setValue)
    {
        var key = channelMessage.Message; //The name of the key that was set
        var value = 0.0;

        //Check if the value is a number. If not, log an error and return.
        if (double.TryParse(setValue, out double result))
        {
            value = result; //The value that was set. (i.e. the price.)
            logger.LogInformation($"Key '{channelMessage.Message}' was set to value '{value}'");
        }
        else
        {
            logger.LogInformation($"Invalid input for key '{key}'. A number is expected.");
            return;
        }        

        // Define the name of the table you created and the column names.
        String tableName = "dbo.inventory";
        String column1Value = "ItemName";
        String column2Value = "Price";        
        
        logger.LogInformation($" '{SQLAddress}'");
        using (SqlConnection connection = new SqlConnection(SQLAddress))
            {
                connection.Open();
                using (SqlCommand command = new SqlCommand())
                {
                    command.Connection = connection;

                    //Form the SQL query to update the database. In practice, you would want to use a parameterized query to prevent SQL injection attacks.
                    //An example query would be something like "UPDATE dbo.inventory SET Price = 1.75 WHERE ItemName = 'Apple'".
                    command.CommandText = "UPDATE " + tableName + " SET " + column2Value + " = " + value + " WHERE " + column1Value + " = '" + key + "'";
                    int rowsAffected = command.ExecuteNonQuery(); //The query execution returns the number of rows affected by the query. If the key doesn't exist, it will return 0.

                    if (rowsAffected == 0) //If key doesn't exist, add it to the database
                 {
                         //Form the SQL query to update the database. In practice, you would want to use a parameterized query to prevent SQL injection attacks.
                         //An example query would be something like "INSERT INTO dbo.inventory (ItemName, Price) VALUES ('Bread', '2.55')".
                        command.CommandText = "INSERT INTO " + tableName + " (" + column1Value + ", " + column2Value + ") VALUES ('" + key + "', '" + value + "')";
                        command.ExecuteNonQuery();

                        logger.LogInformation($"Item " + key + " has been added to the database with price " + value + "");
                    }

                    else {
                        logger.LogInformation($"Item " + key + " has been updated to price " + value + "");
                    }
                }
                connection.Close();
            }

            //Log the time that the function was executed.
            logger.LogInformation($"C# Redis trigger function executed at: {DateTime.Now}");
    }
}

هام

هذا المثال مبسط في البرنامج التعليمي. لاستخدام الإنتاج، نوصي باستخدام استعلامات SQL ذات المعلمات لمنع هجمات حقن SQL.

تكوين سلاسل اتصال

تحتاج إلى تحديث ملف local.settings.json لتضمين سلسلة الاتصال لقاعدة بيانات SQL. أضف إدخالا في Values قسم ل SQLConnectionString. يجب أن يبدو الملف الخاص بك مثل هذا المثال:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
    "redisConnectionString": "<redis-connection-string>",
    "SQLConnectionString": "<sql-connection-string>"
  }
}

للعثور على سلسلة الاتصال Redis، انتقل إلى قائمة الموارد في Azure Cache لمورد Redis. حدد موقع السلسلة في منطقة Access Keys في قائمة Resource.

للعثور على سلسلة الاتصال قاعدة بيانات SQL، انتقل إلى قائمة الموارد في مورد قاعدة بيانات SQL. ضمن الإعدادات، حدد سلاسل الاتصال، ثم حدد علامة التبويب ADO.NET. السلسلة في منطقة ADO.NET (مصادقة SQL).

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

هام

هذا المثال مبسط في البرنامج التعليمي. لاستخدام الإنتاج، نوصي باستخدام Azure Key Vault لتخزين معلومات سلسلة الاتصال أو استخدام Azure EntraID لمصادقة SQL.

إنشاء المشروع وتشغيله

  1. في VS Code، انتقل إلى علامة التبويب Run and debug وقم بتشغيل المشروع.

  2. ارجع إلى Azure Cache لمثيل Redis في مدخل Microsoft Azure، وحدد زر وحدة التحكم لإدخال وحدة تحكم Redis. حاول استخدام بعض SET الأوامر:

    • SET apple 5.25
    • SET bread 2.25
    • SET apple 4.50
  3. مرة أخرى في VS Code، يتم تسجيل المشغلات. للتحقق من أن المشغلات تعمل:

    1. انتقل إلى قاعدة بيانات SQL في مدخل Microsoft Azure.

    2. في قائمة الموارد، حدد محرر الاستعلام.

    3. بالنسبة إلى New Query، قم بإنشاء استعلام باستخدام أمر SQL التالي لعرض أفضل 100 عنصر في جدول المخزون:

      SELECT TOP (100) * FROM [dbo].[inventory]
      

      تأكد من ظهور العناصر المكتوبة في Azure Cache لمثيل Redis هنا.

    لقطة شاشة تعرض المعلومات التي تم نسخها إلى SQL من مثيل ذاكرة التخزين المؤقت.

نشر التعليمات البرمجية إلى تطبيق الوظائف

يعتمد هذا البرنامج التعليمي على البرنامج التعليمي السابق. لمزيد من المعلومات، راجع نشر التعليمات البرمجية إلى دالة Azure.

  1. في VS Code، انتقل إلى علامة التبويب Azure .

  2. ابحث عن اشتراكك وقم بتوسيعه. ثم ابحث عن قسم Function App وقم بتوسيعه.

  3. حدد مع الاستمرار (أو انقر بزر الماوس الأيمن فوق) تطبيق الوظائف، ثم حدد Deploy to Function App.

إضافة معلومات سلسلة الاتصال

يعتمد هذا البرنامج التعليمي على البرنامج التعليمي السابق. لمزيد من المعلومات حول redisConnectionString، راجع إضافة معلومات سلسلة الاتصال.

  1. انتقل إلى تطبيق الوظائف الجديد في مدخل Azure. في قائمة الموارد، حدد Environment variables.

  2. في جزء App الإعدادات، أدخل SQL الاتصال ionString كحقل جديد. بالنسبة إلى Value، أدخل سلسلة الاتصال.

  3. حدد تطبيق.

  4. انتقل إلى جزء Overview وحدد Restart لإعادة تشغيل التطبيق بمعلومات سلسلة الاتصال الجديدة.

تحقق من النشر

بعد انتهاء النشر، ارجع إلى Azure Cache لمثيل Redis واستخدم SET الأوامر لكتابة المزيد من القيم. تأكد من ظهورها أيضا في قاعدة بيانات SQL.

إذا كنت تريد التأكد من أن تطبيق الوظائف يعمل بشكل صحيح، فانتقل إلى التطبيق في المدخل وحدد Log stream من قائمة الموارد. يجب أن تشاهد المشغلات قيد التشغيل هناك، والتحديثات المقابلة التي يتم إجراؤها على قاعدة بيانات SQL الخاصة بك.

إذا كنت تريد مسح جدول قاعدة بيانات SQL دون حذفه، يمكنك استخدام استعلام SQL التالي:

TRUNCATE TABLE [dbo].[inventory]

تنظيف الموارد

إذا كنت تريد الاستمرار في استخدام الموارد التي قمت بإنشائها في هذه المقالة، فاحتفظ بمجموعة الموارد.

وإلا، إذا انتهيت من الموارد، يمكنك حذف مجموعة موارد Azure التي قمت بإنشائها لتجنب الرسوم.

هام

حذف مجموعة الموارد لا يمكن التراجع عنه. عند حذف مجموعة موارد، يتم حذف كافة الموارد الموجودة فيها نهائيًا. تأكد من عدم حذف مجموعة الموارد الخاطئة أو الموارد غير الصحيحة بطريق الخطأ. إذا قمت بإنشاء الموارد داخل مجموعة موارد موجودة تحتوي على الموارد التي تريد الاحتفاظ بها، يمكنك حذف كل مورد على حدة بدلا من حذف مجموعة الموارد.

لحذف مجموعة موارد

  1. سجل الدخول إلى مدخل Azure، وحدد "Resource groups".

  2. حدد مجموعة الموارد التي تريد حذفها.

    إذا كان هناك العديد من مجموعات الموارد، فاستخدم المربع تصفية لأي حقل... ، واكتب اسم مجموعة الموارد التي أنشأتها لهذه المقالة. حدد مجموعة الموارد في قائمة النتائج.

    لقطة شاشة تعرض قائمة بمجموعات الموارد المراد حذفها في جزء العمل.

  3. حدد Delete resource group.

  4. يُطلب منك تأكيد حذف مجموعة الموارد. اكتب اسم مجموعة الموارد لتأكيده، واختر "Delete".

    لقطة شاشة تعرض نموذجا يتطلب اسم المورد لتأكيد الحذف.

بعد مرور لحظات قليلة، يتم حذف مجموعة الموارد وجميع مواردها.

الملخص

يوضح هذا البرنامج التعليمي وبدء استخدام مشغلات Azure Functions في Azure Cache for Redis كيفية استخدام Azure Cache for Redis لتشغيل تطبيقات وظائف Azure. كما أنها توضح كيفية استخدام ذاكرة التخزين المؤقت Azure ل Redis كذاكرة تخزين مؤقت للكتابة في الخلف مع قاعدة بيانات Azure SQL. يعد استخدام Azure Cache for Redis مع Azure Functions مزيجا قويا يمكنه حل العديد من مشكلات التكامل والأداء.