Compartilhar via


Tutorial: Criar um cache write-behind usando o Azure Functions e o Redis no Azure

O objetivo deste tutorial é usar uma instância do Redis Gerenciado do Azure (versão prévia) ou do Cache do Azure para Redis como um cache write-behind. O padrão de gravação em segundo plano neste tutorial mostra como as gravações no cache disparam as gravações correspondentes em um banco de dados SQL (uma instância do serviço Banco de Dados SQL do Azure).

Use o gatilho Redis para o Azure Functions para implementar essa funcionalidade. Nesse cenário, você verá como usar o Redis para armazenar informações de inventário e preços e, ao mesmo tempo, fazer o backup dessas informações em um banco de dados SQL.

Cada novo item ou novo preço gravado no cache é refletido em uma tabela SQL no banco de dados.

Neste tutorial, você aprenderá como:

  • Configurar um banco de dados, um gatilho e cadeias de conexão.
  • Validar se os gatilhos estão funcionando.
  • Implantar código em um aplicativo de funções.

Pré-requisitos

  • Uma assinatura do Azure. Se você não tiver uma assinatura do Azure, crie uma conta gratuita.
  • Complete o tutorial anterior, Comece a usar gatilhos do Azure Functions no Redis no Azure, com esses recursos provisionados:
    • Uma instância do Redis Gerenciado do Azure (versão prévia) ou do Cache do Azure para Redis
    • Instância do Azure Functions
    • Um conhecimento prático de como usar o SQL do Azure
    • Ambiente do Visual Studio Code (VS Code) configurado com pacotes NuGet instalados

Criar e configurar um novo banco de dados SQL

O banco de dados SQL é o banco de dados de suporte para este exemplo. Você pode criar um banco de dados SQL por meio do portal do Azure ou do seu método preferido de automação.

Para obter mais informações sobre como criar um banco de dados SQL, confira Início Rápido: Criar um único banco de dados: Banco de Dados SQL do Azure.

Esse exemplo usa o portal:

  1. Insira um nome de banco de dados e selecione Criar novo para criar um novo servidor para manter o banco de dados.

    Captura de tela da criação de um recurso do SQL do Azure.

  2. Selecione Usar autenticação SQL e insira uma senha e uma entrada de administrador. Lembre-se dessas credenciais ou anote-as. Quando estiver implantando um servidor em produção, use a autenticação do Microsoft Entra.

    Captura de tela das informações de autenticação para um recurso do SQL do Azure.

  3. Acesse a guia Rede e escolha Ponto de extremidade público como método de conexão. Selecione Sim para ambas as regras de firewall exibidas. Esse ponto de extremidade permite o acesso a partir do seu aplicativo de funções do Azure.

    Captura de tela da configuração de rede para um recurso do SQL do Azure.

  4. Após a conclusão da validação, selecione Revisar + criar e, em seguida, Criar. O banco de dados SQL começa a ser implantado.

  5. Após a conclusão da implantação, acesse o recurso no portal do Azure e selecione a guia Editor de consultas. Crie uma nova tabela chamada inventário que contenha os dados que você gravará nela. Use o seguinte comando do SQL para criar uma nova tabela com dois campos:

    • ItemName lista o nome de cada item.
    • Price armazena o preço do item.
    CREATE TABLE inventory (
        ItemName varchar(255),
        Price decimal(18,2)
        );
    

    Captura de tela mostrando a criação de uma tabela no Editor de Consultas de um recurso do SQL do Azure.

  6. Depois que o comando terminar de ser executado, expanda a pasta Tabelas e verifique se a nova tabela foi criada.

Configurar o gatilho Redis

Primeiro, faça uma cópia do mesmo projeto VS Code que você usou no anterior tutorial. Copie a pasta do tutorial anterior com um novo nome, como RedisWriteBehindTrigger, e abra-a no VS Code.

Em segundo lugar, exclua os arquivos RedisBindings.cs e RedisTriggers.cs.

Neste exemplo, você usa o gatilho pub/sub para disparar as notificações keyevent. Os objetivos do exemplo são:

  • Disparar toda vez que ocorrer um evento SET. Um evento SET ocorre quando novas chaves são gravadas na instância do cache ou o valor de uma chave é alterado.
  • Depois que um evento SET for disparado, acesse a instância do cache para encontrar o valor da nova chave.
  • Determine se a chave já existe na tabela inventário no banco de dados SQL.
    • Nesse caso, atualize o valor dessa chave.
    • Caso contrário, escreva uma nova linha com a chave e seu valor.

Para configurar o gatilho:

  1. Importe o pacote NuGet System.Data.SqlClient para habilitar a comunicação com o banco de dados SQL. Vá para o terminal do VS Code e use o seguinte comando:

      dotnet add package System.Data.SqlClient
    
  2. Crie um novo arquivo chamado RedisFunction.cs. Certifique-se de ter excluído os arquivos RedisBindings.cs e RedisTriggers.cs.

  3. Copie e cole o seguinte código em RedisFunction.cs para substituir o código existente:

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

Importante

Este exemplo é simplificado para o tutorial. Para uso em produção, recomendamos que você use consultas SQL parametrizadas para evitar ataques de injeção de SQL.

Configurar cadeias de conexão

Você precisa atualizar o arquivo local.settings.json para incluir a cadeia de conexão do seu banco de dados SQL. Adicione uma entrada na seção Values para SQLConnectionString. Seu arquivo deve ser semelhante a este exemplo:

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

Para localizar a cadeia de conexão do Redis, vá para o menu de recursos no recurso Redis Gerenciado do Azure ou Cache do Azure para Redis. Localize a cadeia de caracteres na área Chaves de Acesso no menu Recurso.

Para localizar a cadeia de conexão do banco de dados SQL, vá para o menu de recursos no recurso de banco de dados SQL. Em Configurações, selecione Cadeias de conexão e, em seguida, selecione a guia ADO.NET. A cadeia de caracteres está na área do ADO.NET (autenticação SQL).

Você precisa inserir manualmente a senha para a cadeia de conexão do banco de dados SQL, pois a senha não é colada automaticamente.

Importante

Este exemplo é simplificado para o tutorial. Para uso em produção, recomendamos que você use o Azure Key Vault para armazenar informações da cadeia de conexão ou use o Microsoft Entra ID no Azure para autenticação do SQL.

Compilar e executar o projeto

  1. No VS Code, acesse a guia Executar e depurar e execute o projeto.

  2. Volte para a sua instância do Redis no portal do Azure e selecione o botão Console para entrar no console do Redis. Experimente usar alguns comandos SET:

    • SET apple 5.25
    • SET bread 2.25
    • SET apple 4.50

Importante

A ferramenta de console ainda não está disponível para Redis Gerenciados do Azure. Alternativamente, pense em usar a redis-cli ou uma ferramenta como o Redis Insight para executar comandos diretamente na instância do Redis.

  1. De volta ao VS Code, os gatilhos estão sendo registrados. Para validar se os gatilhos estão funcionando:

    1. Acesse o banco de dados SQL no portal do Azure.

    2. No menu de recursos, selecione Editor de consultas.

    3. Para Nova Consulta, crie uma consulta com o seguinte comando SQL para exibir os 100 principais itens na tabela de inventário:

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

      Confirme se os itens gravados na sua instância do Redis aparecem aqui.

    Captura de tela mostrando que as informações foram copiadas da instância de cache para o SQL.

Implantar o código no seu aplicativo de funções

Este tutorial se baseia no tutorial anterior. Para obter mais informações, confira Implantar código em uma função do Azure.

  1. No VS Code, acesse a guia Azure.

  2. Encontre sua assinatura e expanda-a. Em seguida, encontre a seção Aplicativo de Funções e expanda-a.

  3. Selecione e mantenha pressionado (ou clique com o botão direito do mouse) o aplicativo de função e, em seguida, selecione Implantar no Aplicativo de Funções.

Adicionar informações da cadeia de conexão

Este tutorial se baseia no tutorial anterior. Para obter mais informações sobre a redisConnectionString, confira Adicionar informações de cadeia de conexão.

  1. Vá para seu aplicativo de funções no portal do Azure. No menu de recursos, selecione Variáveis de ambiente.

  2. No painel Configurações do aplicativo, insira SQLConnectionString como um novo campo. Em Value, insira sua cadeia de conexão.

  3. Escolha Aplicar.

  4. Vá para a folha Visão geral e selecione Reiniciar para reiniciar o aplicativo com as novas informações da cadeia de conexão.

Verificar implantação

Após a implantação ser concluída, volte para a sua instância do Redis e use os comandos SET para gravar mais valores. Confirme se eles também aparecem no banco de dados SQL.

Se quiser confirmar que o aplicativo de função está funcionando corretamente, acesse o aplicativo no portal e selecione Fluxo de logs no menu de recursos. Você deverá ver os gatilhos em execução e as atualizações correspondentes sendo feitas no banco de dados SQL.

Se você quiser limpar a tabela do banco de dados SQL sem excluí-la, poderá usar a seguinte consulta SQL:

TRUNCATE TABLE [dbo].[inventory]

Limpar os recursos

Se quiser continuar a usar os recursos que você criou neste artigo, conserve o grupo de recursos.

Caso contrário, se não pretende mais usar os recursos, você poderá excluir o grupo de recursos criado no Azure para evitar a cobrança.

Importante

A exclusão de um grupo de recursos é irreversível. Ao excluir o grupo de recursos, todos os recursos nele são excluídos permanentemente. Não exclua acidentalmente o grupo de recursos ou os recursos incorretos. Se você criou os recursos dentro de um grupo de recursos existente que contém recursos que você quer manter, você pode excluir cada recurso individualmente em vez de excluir o grupo de recursos.

Para excluir um grupo de recursos

  1. Entre no portal do Azure e selecione Grupos de recursos.

  2. Selecione o grupo de recursos que você quer excluir.

    Se existirem muitos grupos de recursos, use a caixa Filtrar para qualquer campo... e digite o nome do seu grupo de recursos que você criou para este artigo. Selecione o grupo de recursos na lista de resultados.

    Captura de tela mostrando uma lista dos grupos de recursos a serem excluídos no painel de trabalho.

  3. Selecione Excluir grupo de recursos.

  4. Você receberá uma solicitação para confirmar a exclusão do grupo de recursos. Digite o nome do grupo de recursos para confirmar e selecione Excluir.

    Captura de tela mostrando um formulário que requer que a exclusão do nome do recurso seja confirmada.

Após alguns instantes, o grupo de recursos, e todos os recursos nele são excluídos.

Resumo

Este tutorial e o Comece a usar gatilhos do Azure Functions no Redis no Azure mostram como usar gatilhos e vinculações do Redis em aplicativos de funções do Azure. Mostram também como usar o Redis como um cache write-behind com o Banco de Dados SQL do Azure. Usar o Redis Gerenciado do Azure ou o Cache do Azure para Redis com o Azure Functions constitui uma combinação poderosa que pode resolver muitos problemas de integração e desempenho.