Freigeben über


Tutorial: Erstellen eines Write-Behind-Cache mithilfe von Azure Functions und Azure Cache for Redis

Das Ziel dieses Tutorials besteht darin, eine Azure Cache for Redis-Instanz als Write-Behind-Cache zu verwenden. Das Write-Behind-Muster in diesem Tutorial zeigt, wie Schreibvorgänge in den Cache entsprechende Schreibvorgänge in eine SQL-Datenbank (eine Instanz des Azure SQL-Datenbank-Diensts) auslösen.

Sie verwenden den Redis-Trigger für Azure Functions, um diese Funktionalität zu implementieren. In diesem Szenario sehen Sie, wie Azure Cache for Redis verwendet wird, um Bestands- und Preisinformationen zu speichern. Gleichzeitig werden diese Informationen in einer SQL-Datenbank gesichert.

Jedes neue Element oder jeder neue Preis, das bzw. der in den Cache geschrieben wird, wird dann in einer SQL-Tabelle in der Datenbank wiedergegeben.

In diesem Tutorial lernen Sie Folgendes:

  • Konfigurieren einer Datenbank, eines Triggers und von Verbindungszeichenfolgen
  • Überprüfen, ob Trigger funktionieren
  • Bereitstellen von Code in einer Funktions-App

Voraussetzungen

  • Ein Azure-Abonnement. Wenn Sie kein Azure-Abonnement besitzen, können Sie ein kostenloses Konto erstellen.
  • Abschluss des vorherigen Tutorials Erste Schritte mit Azure Functions-Triggern in Azure Cache for Redis mit den folgenden bereitgestellten Ressourcen:
    • Azure Cache for Redis-Instanz
    • Azure Functions-Instanz
    • Fundierte Kenntnisse in Bezug auf die Verwendung von Azure SQL
    • VS Code-Umgebung (Visual Studio Code), eingerichtet mit installierten NuGet-Paketen

Erstellen und Konfigurieren einer neuen SQL-Datenbank

Die SQL-Datenbank ist die Sicherungsdatenbank für dieses Beispiel. Sie können eine SQL-Datenbank-Instanz über das Azure-Portal oder über Ihre bevorzugte Automatisierungsmethode erstellen.

Weitere Informationen zum Erstellen einer SQL-Datenbank finden Sie unter Schnellstart: Erstellen einer Einzeldatenbank – Azure SQL-Datenbank.

In diesem Beispiel wird das Portal verwendet:

  1. Geben Sie einen Datenbanknamen ein, und wählen Sie Neu erstellen aus, um einen neuen Server für die Datenbank zu erstellen.

    Screenshot: Erstellen einer Azure SQL-Ressource

  2. Wählen Sie SQL-Authentifizierung verwenden aus, und geben Sie einen Administratoranmeldenamen und das Kennwort ein. Sie müssen sich diese Anmeldeinformationen merken oder notieren. Wenn Sie einen Server in der Produktion bereitstellen, verwenden Sie stattdessen die Microsoft Entra-Authentifizierung.

    Screenshot: Authentifizierungsinformationen für eine Azure SQL-Ressource

  3. Wechseln Sie zur Registerkarte Netzwerk, und wählen Sie Öffentlicher Endpunkt als Verbindungsmethode aus. Wählen Sie Ja für beide angezeigten Firewallregeln aus. Dieser Endpunkt ermöglicht den Zugriff über Ihre Azure-Funktions-App.

    Screenshot: Netzwerkeinstellung für eine Azure SQL-Ressource

  4. Wählen Sie nach Abschluss der Überprüfung Überprüfen + erstellen und dann Erstellen aus. Die SQL-Datenbank wird bereitgestellt.

  5. Wechseln Sie nach Abschluss der Bereitstellung zur Ressource im Azure-Portal, und wählen Sie die Registerkarte Abfrage-Editor aus. Erstellen Sie eine neue Tabelle namens Bestand, die die von Ihnen geschriebenen Daten aufnimmt. Verwenden Sie den folgenden SQL-Befehl, um eine neue Tabelle mit zwei Feldern zu erstellen:

    • ItemName listet die Namen der einzelnen Elemente auf.
    • Price speichert den Preis der Elemente.
    CREATE TABLE inventory (
        ItemName varchar(255),
        Price decimal(18,2)
        );
    

    Screenshot: Erstellung einer Tabelle im Abfrage-Editor einer Azure SQL-Ressource

  6. Erweitern Sie nach Abschluss dieses Befehls den Ordner Tabellen, und überprüfen Sie, ob die neue Tabelle erstellt wurde.

Konfigurieren des Redis-Triggers

Erstens: Erstellen Sie eine Kopie des VS Code-Projekts, das Sie im vorherigen Tutorial verwendet haben. Kopieren Sie den Ordner aus dem vorherigen Tutorial unter einen neuen Namen, z. B. RedisWriteBehindTrigger, und öffnen Sie ihn in VS Code.

Zweitens: Löschen Sie die Dateien RedisBindings.cs und RedisTriggers.cs.

In diesem Beispiel verwenden Sie den Pub/Sub-Trigger, um keyevent-Benachrichtigungen auszulösen. Die Ziele des Beispiels sind:

  • Auslösung bei jedem SET-Ereignis. Ein SET-Ereignis tritt auf, wenn neue Schlüssel in die Cache-Instanz geschrieben werden oder der Wert eines Schlüssels geändert wird.
  • Nachdem ein SET-Ereignis ausgelöst wurde, greifen Sie auf die Cache-Instanz zu, um den Wert des neuen Schlüssels zu ermitteln.
  • Ermitteln Sie, ob der Schlüssel bereits in der Tabelle Bestand in der SQL-Datenbank vorhanden ist.
    • Wenn ja, aktualisieren Sie den Wert dieses Schlüssels.
    • Wenn nicht, schreiben Sie eine neue Zeile mit dem Schlüssel und dem zugehörigen Wert.

So konfigurieren Sie den Trigger

  1. Importieren Sie das NuGet-Paket System.Data.SqlClient, um die Kommunikation mit der SQL-Datenbank zu ermöglichen. Wechseln Sie zum VS Code-Terminal, und verwenden Sie den folgenden Befehl:

      dotnet add package System.Data.SqlClient
    
  2. Erstellen Sie eine neue Datei mit dem Namen RedisFunction.cs. Stellen Sie sicher, dass Sie die Dateien RedisBindings.cs und RedisTriggers.cs gelöscht haben.

  3. Kopieren Sie dann den folgenden Code, und fügen Sie ihn in RedisFunction.cs ein, um den vorhandenen Code zu ersetzen:

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}");
    }
}

Wichtig

Dieses Beispiel wurde für das Tutorial vereinfacht. Für die Verwendung in der Produktion wird empfohlen, parametrisierte SQL-Abfragen zu verwenden, um Angriffe durch Einschleusung von SQL-Befehlen zu verhindern.

Konfigurieren von Verbindungszeichenfolgen

Sie müssen die Datei local.settings.json aktualisieren, um die Verbindungszeichenfolge für Ihre SQL-Datenbank einzuschließen. Fügen Sie einen Eintrag im Abschnitt Values für SQLConnectionString. Die Datei sollte wie dieses Beispiel aussehen:

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

Um die Redis-Verbindungszeichenfolge zu ermitteln, wechseln Sie zum Ressourcenmenü in der Azure Cache for Redis-Ressource. Suchen Sie die Zeichenfolge im Bereich Zugriffsschlüssel im Menü „Ressource“.

Um die Verbindungszeichenfolge der SQL-Datenbank zu ermitteln, wechseln Sie zum Ressourcenmenü in der SQL-Datenbankressource. Wählen Sie unter Einstellungen die Option Verbindungszeichenfolgen und dann die Registerkarte ADO.NET aus. Die Zeichenfolge befindet sich im Bereich ADO.NET (SQL-Authentifizierung).

Sie müssen das Kennwort für die Verbindungszeichenfolge Ihrer SQL-Datenbank manuell eingeben, da das Kennwort nicht automatisch eingefügt wird.

Wichtig

Dieses Beispiel wurde für das Tutorial vereinfacht. Für die Verwendung in der Produktion wird empfohlen, Azure Key Vault zum Speichern von Verbindungszeichenfolgeninformationen oder Azure EntraID für die SQL-Authentifizierung zu verwenden.

Erstellen und Ausführen des Projekts

  1. Wechseln Sie zur Registerkarte Ausführen und debuggen in VS Code, und führen Sie das Projekt aus.

  2. Navigieren Sie zurück zu Ihrer Azure Cache for Redis-Instanz im Azure-Portal, und wählen Sie die Schaltfläche Konsole aus, um die Redis-Konsole aufzurufen. Probieren Sie einige der SET-Befehle aus:

    • SET apple 5.25
    • SET bread 2.25
    • SET apple 4.50
  3. Wieder zurück in VS Code werden die Trigger registriert. So überprüfen Sie, ob die Trigger funktionieren

    1. Wechseln Sie zur SQL-Datenbank im Azure-Portal.

    2. Wählen Sie dann im Menü „Ressource“ die Option Abfrage-Editor aus.

    3. Erstellen Sie unter Neue Abfrage eine Abfrage mit dem folgenden SQL-Befehl, um die 100 wichtigsten Elemente in der Bestandstabelle anzuzeigen:

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

      Vergewissern Sie sich, dass die in Ihre Azure Cache for Redis-Instanz geschriebenen Elemente hier angezeigt werden.

    Screenshot: Die Informationen wurden aus der Cache-Instanz in SQL kopiert.

Bereitstellen des Codes in Ihrer Funktions-App

Dieses Tutorial baut auf dem vorherigen Tutorial auf. Weitere Informationen finden Sie unter Bereitstellen von Code in einer Azure-Funktion.

  1. Wechseln Sie in VS Code zur Registerkarte Azure.

  2. Suchen Sie Ihr Abonnement, und erweitern Sie es. Navigieren Sie dann zum Abschnitt Funktions-App, und erweitern Sie diesen.

  3. Wählen Sie Ihre Funktions-App bei gedrückter Maustaste aus (oder klicken Sie mit der rechten Maustaste darauf), und wählen Sie dann In Funktions-App bereitstellen aus.

Informationen zur Verbindungszeichenfolge hinzufügen

Dieses Tutorial baut auf dem vorherigen Tutorial auf. Weitere Informationen zu redisConnectionString finden Sie unter Informationen zur Verbindungszeichenfolge hinzufügen.

  1. Navigieren Sie im Azure-Portal zu Ihrer Funktions-App. Wählen Sie im Ressourcenmenü die Option Umgebungsvariablen aus.

  2. Geben Sie im Bereich App-Einstellungen SQLConnectionString als neues Feld ein. Geben Sie unter Wert Ihre Verbindungszeichenfolge an.

  3. Wählen Sie Übernehmen.

  4. Wechseln Sie zum Blatt Übersicht, und wählen Sie Neustarten aus, um die App mit den neuen Verbindungszeichenfolgeninformationen neu zu starten.

Überprüfen der Bereitstellung

Wenn die Bereitstellung abgeschlossen ist, kehren Sie zu Ihrer Azure Cache for Redis-Instanz zurück, und verwenden Sie SET-Befehle, um weitere Werte zu schreiben. Vergewissern Sie sich, dass sie auch in Ihrer SQL-Datenbank angezeigt werden.

Wenn Sie überprüfen möchten, ob Ihre Funktions-App ordnungsgemäß funktioniert, wechseln Sie im Portal zur App, und wählen Sie im Menü „Ressource“ die Option Protokollstream aus. Sie sollten sehen, dass die Trigger ausgeführt werden und dass die entsprechenden Aktualisierungen an Ihrer SQL-Datenbank vorgenommen werden.

Wenn Sie die SQL-Datenbanktabelle bereinigen möchten, ohne sie zu löschen, können Sie die folgende SQL-Abfrage verwenden:

TRUNCATE TABLE [dbo].[inventory]

Bereinigen von Ressourcen

Wenn Sie die in diesem Artikel erstellten Ressourcen weiterhin verwenden möchten, behalten Sie die Ressourcengruppe bei.

Wenn Sie die Ressourcen nicht mehr benötigen, können Sie die erstellte Azure-Ressourcengruppe ansonsten löschen, um Kosten im Zusammenhang mit den Ressourcen zu vermeiden.

Warnung

Das Löschen einer Ressourcengruppe kann nicht rückgängig gemacht werden. Beim Löschen einer Ressourcengruppe werden alle darin enthaltenen Ressourcen unwiderruflich gelöscht. Achten Sie daher darauf, dass Sie nicht versehentlich die falsche Ressourcengruppe oder die falschen Ressourcen löschen. Falls Sie die Ressourcen in einer vorhandenen Ressourcengruppe erstellt haben, die Ressourcen enthält, die Sie behalten möchten, können Sie anstelle der Ressourcengruppe jede Ressource einzeln löschen.

Löschen einer Ressourcengruppe

  1. Melden Sie sich beim Azure-Portal an, und wählen Sie anschließend Ressourcengruppen aus.

  2. Wählen Sie die zu löschende Ressourcengruppe aus.

    Wenn viele Ressourcengruppen vorhanden sind, verwenden Sie das Feld Nach einem beliebigen Feld filtern, und geben Sie den Namen der Ressourcengruppe ein, die Sie für diesen Artikel erstellt haben. Wählen Sie in der Liste der Suchergebnisse die Ressourcengruppe aus.

    Screenshot einer Liste der Ressourcengruppen, die zum Löschen ausgewählt werden können.

  3. Wählen Sie die Option Ressourcengruppe löschen.

  4. Geben Sie im Bereich Ressourcengruppe löschen zur Bestätigung den Namen Ihrer Ressourcengruppe ein, und wählen Sie dann Löschen aus.

    Screenshot eines Felds, in dem der Ressourcenname eingegeben werden muss, um den Löschvorgang zu bestätigen.

Innerhalb kurzer Zeit werden die Ressourcengruppe und alle darin enthaltenen Ressourcen gelöscht.

Zusammenfassung

In diesem Tutorial und unter Erste Schritte mit Azure Functions-Triggern in Azure Cache for Redis erfahren Sie, wie Sie Azure Cache for Redis zum Auslösen von Azure-Funktions-Apps verwenden. Außerdem wird gezeigt, wie Sie Azure Cache for Redis als Write-Behind-Cache mit Azure SQL-Datenbank verwenden. Die Verwendung von Azure Cache for Redis mit Azure Functions ist eine leistungsstarke Kombination, mit der Sie viele Integrations- und Leistungsprobleme lösen können.