共用方式為


教學課程:使用 Azure Functions 和 Azure Redis 建立寫入後置快取

本教學課程的目標是使用 Azure 受控 Redis(預覽版)或 Azure Cache for Redis 實例作為 寫入後置快取。 本教學課程中的寫入後置模式示範快取的寫入如何觸發 SQL 資料庫的對應寫入 (Azure SQL Database 服務的執行個體)。

您會使用 Azure Functions 的 Redis 觸發程序來實作此功能。 在此案例中,您會瞭解如何使用 Redis 來儲存庫存和定價資訊,同時備份 SQL 資料庫中的資訊。

每個寫入快取的新項目或新價格都會反映在資料庫的 SQL 資料表中。

在本教學課程中,您會了解如何:

  • 設定資料庫、觸發程序和連接字串。
  • 驗證觸發程序是否正常運作。
  • 將程式碼部署至函數應用程式。

必要條件

  • Azure 訂用帳戶。 如果您沒有 Azure 訂用帳戶,請建立免費帳戶
  • 完成上一個教學課程: 開始使用 Azure Redis 中的 Azure Functions 觸發程式,並布建下列資源:
    • Azure 受控 Redis (預覽版) 或 Azure Cache for Redis 實例
    • Azure Functions 執行個體
    • 使用 Azure SQL 的使用知識
    • 已安裝 NuGet 套件的 Visual Studio Code (VS Code) 環境設定

建立並設定新的 SQL 資料庫

SQL 資料庫是此範例的備份資料庫。 您可透過 Azure 入口網站或偏好的自動化方法建立 SQL 資料庫。

如需建立 SQL 資料庫的詳細資訊,請參閱快速入門:建立單一資料庫 - Azure SQL Database

此範例使用入口網站:

  1. 輸入資料庫名稱並選擇 [新建] 來建立新伺服器以保存資料庫。

    建立 Azure SQL 資源的螢幕擷取畫面。

  2. 選取 [使用 SQL 驗證],並輸入系統管理員登入和密碼。 請務必記住這些認證或將其寫下。 在實際執行環境中部署伺服器後,請改為使用 Microsoft Entra 驗證。

    Azure SQL 資源的驗證資訊螢幕擷取畫面。

  3. 移至 [網路] 索引標籤,然後選擇 [公用端點] 作為連線方法。 針對顯示的兩個防火牆規則,選擇 [是]。 此端點允許從 Azure 函數應用程式進行存取。

    Azure SQL 資源的網路設定螢幕擷取畫面。

  4. 驗證完成後,選擇 [檢閱 + 建立],然後選擇 [建立]。 SQL 資料庫開始部署。

  5. 部署完成後,請移至 Azure 入口網站中的資源,然後選擇 [查詢編輯器] 索引標籤。建立名為 [庫存] 的新資料表以保存所要寫入的資料。 使用下列 SQL 命令以建立新資料表,並包含下列兩個欄位:

    • ItemName 列出每個項目的名稱。
    • Price 儲存項目的價格。
    CREATE TABLE inventory (
        ItemName varchar(255),
        Price decimal(18,2)
        );
    

    在 Azure SQL 資源的查詢編輯器中建立資料表的螢幕擷取畫面。

  6. 命令完成執行後,請展開 [資料表] 資料夾並驗證已建立新的資料表。

設定 Redis 觸發程序

首先建立上一個教學課程 (部分機器翻譯) 所使用相同 VS Code 專案的複本。 在新的名稱下複製上一個教學課程的資料夾,例如 RedisWriteBehindTrigger,並在 VS Code 中開啟。

其次,刪除 RedisBindings.csRedisTriggers.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.csRedisTriggers.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 受控 Redis 或 Azure Cache for Redis 資源中的資源功能表。 在 [資源] 功能表的 [存取金鑰] 區域中找到字串。

若要尋找 SQL 資料庫連接字串,請移至 SQL 資料庫資源中的資源功能表。 在 [設定] 下,選擇 [連接字串],然後選擇 [ADO.NET] 索引標籤。字串位於 [ADO.NET (SQL 驗證)] 區域。

您必須手動輸入 SQL 資料庫連接字串的密碼,因為不會自動貼上密碼。

重要

針對教學課程,已簡化此範例。 若要使用生產環境,建議您使用 Azure 金鑰保存庫 來儲存 連接字串 資訊,或使用 Azure Microsoft Entra ID 進行 SQL 驗證

建置和執行專案

  1. 在 VS Code 中,移至 [執行和偵錯] 索引標籤並執行專案。

  2. 返回 Azure 入口網站 中的 Redis 實例,然後選取 [主控台] 按鈕以輸入 Redis 主控台。 嘗試使用一些指令 SET

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

重要

Azure 受控 Redis 尚無法使用主控台工具。 相反地,請考慮使用 redis-cli 或 Redis Insight 之類的工具,直接在 Redis 實例上執行命令。

  1. 返回 VS Code,觸發程序正在註冊。 若要驗證觸發程序是否正常運作:

    1. 移至 Azure 入口網站中的 SQL 資料庫。

    2. 在資源功能表上,選擇 [查詢編輯器]

    3. 針對 [新增查詢],使用下列 SQL 命令建立查詢以檢視庫存資料表中的前 100 個項目:

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

      確認寫入 Redis 實例的專案會出現在這裡。

    螢幕擷取畫面顯示資訊已從快取執行個體複製至 SQL。

將程式碼部署至函數應用程式

本教學課程會以上一個教學課程為基礎來建置。 如詳細資訊,請參閱將程式碼部署至 Azure 函數

  1. 在 VS Code 中,移至 [Azure] 索引標籤。

  2. 尋找訂用帳戶並將其展開。 然後,尋找 [函數應用程式] 並展開該區段。

  3. 選擇並保存 (或以滑鼠右鍵按一下) 函數應用程式,然後選擇 [部署至函數應用程式]

新增連接字串資訊

本教學課程會以上一個教學課程為基礎來建置。 如需 redisConnectionString 的詳細資訊,請參閱新增連接字串資訊

  1. 移至 Azure 入口網站中的函數應用程式。 在資源功能表上,選取 [環境變數]

  2. 在 [應用程式設定] 窗格中,輸入 SQLConnectionString 作為新欄位。 針對 [值],輸入連接字串。

  3. 選取套用

  4. 移至 [概觀] 窗格,然後選取 [重新啟動] 以使用新的連接字串資訊重新啟動應用程式。

驗證部署

部署完成之後,請返回您的 Redis 實例,並使用 SET 命令來撰寫更多值。 確認這些值顯示在 SQL 資料庫中。

如果您要確認函數應用程式正常運作,請移至入口網站中的應用程式並從資源功能表選擇 [記錄資料流]。 您應在這裡看到觸發程序正在執行並正在對 SQL 資料庫進行對應更新。

如果您要清除 SQL 資料庫資料表而不加以刪除,您可使用下列 SQL 查詢:

TRUNCATE TABLE [dbo].[inventory]

清除資源

如果您想要繼續使用在本文中建立的資源,請保留該資源群組。

否則,若已完成資源使用,則可刪除您建立的 Azure 資源群組,以避免衍生費用。

重要

刪除資源群組是無法回復的動作。 當您刪除資源群組時,其中包含的所有資源都將永久刪除。 請確定您不會不小心刪除錯誤的資源群組或資源。 如果您是在包含需保留資源的現有資源群組內部建立資源,則可以個別刪除每個資源,而不必刪除整個資源群組。

刪除資源群組

  1. 登入 Azure 入口網站,然後選取 [資源群組]

  2. 選取您想要刪除的資源群組。

    如果有許多資源群組,請使用 [篩選任何欄位] 方塊,並輸入您針對本文所建立資源群組的名稱。 選取結果清單中的資源群組。

    此螢幕擷取畫面顯示工作窗格中要刪除的資源群組清單。

  3. 選取 [刪除資源群組]

  4. 系統將會要求您確認是否刪除資源群組。 輸入您的資源群組名稱以進行確認,然後選取 [刪除]

    此螢幕擷取畫面顯示需要資源名稱才能確認刪除的表單。

不久後,系統便會刪除該資源群組及其所有的資源。

摘要

本教學課程和 開始使用 Azure Redis 中的 Azure Functions 觸發程式會示範如何在 Azure 函式應用程式中使用 Redis 觸發程式和系結。 它們也會示範如何使用 Redis 作為 Azure SQL 資料庫 的回寫快取。 搭配 Azure Functions 使用 Azure 受控 Redis 或 Azure Cache for Redis 是一個功能強大的組合,可解決許多整合和效能問題。