使用 .NET 與 Azure Cache for Redis 互動

已完成

一般而言,用戶端應用程式會使用用戶端程式庫以形成要求,並在 Redis 快取上執行命令。 您可以直接從 Redis 用戶端頁面取得用戶端程式庫清單。

在 Redis 快取上執行命令

StackExchange.Redis 是一個適用於 .NET 語言的熱門高效能 Redis 用戶端。 此套件可以透過 NuGet 取得,而且可以使用命令列或 IDE,新增至您的 .NET 程式碼。 以下是如何使用用戶端的範例。

使用 StackExchange.Redis 連線到您的 Redis 快取

您應該記得我們使用過主機位址、連接埠號碼與存取金鑰來連線到 Redis 伺服器。 Azure 也為一些 Redis 用戶端提供連接字串,這會將此資料包裝成單一字串。 看起來如下所示 (在 cache-namepassword-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.ConnectConnectionMultiplexer.ConnectAsync 方法建立 ConnectionMultiplexer 執行個體,傳入連接字串或 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,您就可以執行 3 個主要事項:

  • 存取 Redis 資料庫。
  • 使用此課程模組範圍之外 Redis 的發行者/訂閱者功能。
  • 針對維護或監視目的存取個別伺服器。

存取 Redis 資料庫

IDatabase 類型代表 Redis 資料庫。 您可以使用 GetDatabase() 方法來擷取資料庫:

IDatabase db = redisConnection.GetDatabase();

提示

透過 GetDatabase 傳回的物件是輕量型物件,而且不需要儲存。 只有 ConnectionMultiplexer 必須保持運作。

一旦您擁有 IDatabase 物件,您可以執行方法來與快取互動。 所有方法都有同步和非同步版本,會傳回 Task 物件,讓其與 asyncawait 關鍵字相容。

以下是在快取中儲存索引鍵/值的範例:

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 類型的索引鍵。 這個類別具有 stringbyte[] 之間隱含的轉換,允許使用文字與二進位機碼,沒有任何複雜度。 值是由 RedisValue 型別表示。 如同使用 RedisKey,有隱含的轉換,可讓您傳遞 stringbyte[]

其他常見作業

IDatabase 介面包含可以與 Redis 快取搭配使用的其他數種方法。 有方法可以與雜湊、清單、集合和已排序集合搭配使用。

以下是一些可以與單一索引鍵搭配使用的較常見項目,您可以針對介面讀取原始程式碼,以查看完整清單。

方法 描述
CreateBatch 建立作業群組,以單一單位的形式傳送到伺服器,但不一定會當做一個單位來處理。
CreateTransaction 建立作業群組,以單一單位的形式傳送到伺服器,且作為單一單位在伺服器上進行處理。
KeyDelete 刪除索引鍵/值。
KeyExists 傳回指定索引鍵是否存在於快取中的資訊。
KeyExpire 設定機碼的存留時間 (TTL) 到期日。
KeyRename 重新命名機碼。
KeyTimeToLive 傳回機碼的 TTL。
KeyType 傳回儲存在索引鍵的值類型字串表示法。 傳回的不同類型為:字串、清單、集合、zset 和雜湊。

執行其他命令

IDatabase 物件具有 ExecuteExecuteAsync 方法,可用來將文字命令傳遞給 Redis 伺服器。 例如:

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

ExecuteExecuteAsync 方法會傳回 RedisResult 物件,這是資料預留位置,其中包含兩個屬性:

  • Resp2Type 會傳回 string,表示結果類型 - STRINGINTEGER 等等。
  • IsNull,當結果為 null 時設定要偵測的 true/false 值。

然後,您可以在 RedisResult 上使用 ToString(),以取得實際傳回值。

您可以使用 Execute 來執行任何支援的命令 - 例如,我們可以取得連線到快取的所有用戶端 ("CLIENT LIST"):

var result = await db.ExecuteAsync("client", "list");
Console.WriteLine($"Type = {result.Resp2Type}\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.Json 程式庫,將此物件的執行個體轉換為字串:

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"

清除連線

當不再需要連線時,您可以 Dispose ConnectionMultiplexer。 這樣會關閉所有連線,並且關閉與伺服器的通訊。

redisConnection.Dispose();
redisConnection = null;