.NET を使用して、Azure Cache for Redis と対話する

完了

通常、クライアント アプリケーションはクライアント ライブラリを使用して要求を作成し、Redis Cache でコマンドを実行します。 クライアント ライブラリの一覧は、Redis クライアント ページから直接取得できます。

Redis Cache でコマンドを実行する

.NET 言語用に人気のある高性能な Redis クライアントは StackExchange.Redis です。 このパッケージは NuGet から入手でき、コマンド ラインまたは IDE を使用して .NET コードに追加できます。 次はクライアントの使い方の例です。

StackExchange.Redis を使用して Redis Cache に接続する

Redis サーバーに接続するには、ホスト アドレス、ポート番号、アクセス キーを使用します。 Azure では、一部の Redis クライアント用に、このデータを 1 つの文字列にまとめた接続文字列も提供されます。 それは次のようになります (cache-name および password-here フィールドには実際の値が入力されています)。

[cache-name].redis.cache.windows.net:6380,password=[password-here],ssl=True,abortConnect=False

この文字列を StackExchange.Redis に渡して、サーバーへの接続を作成できます。

末尾にさらに 2 つのパラメーターがあることに注意してください。

  • ssl - 通信を暗号化できます。
  • abortConnection - その時にサーバーが使用できなくても接続を作成できます。

クライアント ライブラリを構成するために文字列に追加できる他の省略可能なパラメーターがいくつかあります。

接続を作成する

StackExchange.Redis の主な接続オブジェクトは StackExchange.Redis.ConnectionMultiplexer クラスです。 このオブジェクトは、Redis サーバー (またはサーバーのグループ) への接続プロセスを抽象化します。 接続を効率的に管理するように最適化されており、キャッシュにアクセスする必要がある間は保持されることを目的としています。

静的 ConnectionMultiplexer.Connect メソッドまたは ConnectionMultiplexer.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 オブジェクトを取得したら、キャッシュを操作するメソッドを実行できます。 すべてのメソッドには同期バージョンと非同期バージョンがあります。非同期バージョンは、async および await キーワードに対応できるようにするための Task オブジェクトを返します。

次はキーと値をキャッシュに格納する例です。

bool wasSet = db.StringSet("favorite:flavor", "i-love-rocky-road");

StringSet メソッドは、値が設定されているか (true)、設定されていないか (false) を示す bool を返します。 値は 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 と同様に、string または byte[] を渡すことができるように、暗黙的な変換が適切に行われます。

その他の一般的な操作

IDatabase インターフェイスには、Redis Cache で動作する他の複数のメソッドがあります。 ハッシュ、リスト、セット、順序付けされたセットを操作するメソッドがあります。

ここでは、単一キーで動作するより一般的なものを紹介します。完全なリストについては、このインターフェイスのソース コードを参照してください。

メソッド 説明
CreateBatch 単一ユニットとしてサーバーに送信されますが、必ずしもユニットとして処理されるわけではない操作のグループを作成します。
CreateTransaction 単一ユニットとしてサーバーに送信され、サーバー上で単一ユニットとして処理される操作のグループを作成します。
KeyDelete キーと値を削除します。
KeyExists 特定のキーがキャッシュに存在するかどうかを返します。
KeyExpire キーの Time to Live (TTL) の有効期限を設定します。
KeyRename キーの名前を変更します。
KeyTimeToLive キーの TTL を返します。
KeyType キーに格納されている値の型の文字列表現を返します。 返される型は、文字列、list、set、zset、hash です。

他のコマンドを実行する

IDatabase オブジェクトには、テキスト コマンドを Redis サーバーに渡すときに使用できる Execute メソッドと ExecuteAsync メソッドがあります。 次に例を示します。

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

Execute メソッドと ExecuteAsync メソッドは RedisResult オブジェクトを返します。これは次の 2 つのプロパティを含むデータ ホルダーです。

  • Resp2Type - 結果の型 (STRINGINTEGER など) を示す string を返します。
  • IsNull - 結果が null かどうかを検出する true/false 値。

RedisResultToString() を使用して、実際の戻り値を取得できます。

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"

接続をクリーンアップする

接続が不要になったら、ConnectionMultiplexerDispose できます。 これにより、すべての接続が閉じられ、サーバーとの通信がシャットダウンされます。

redisConnection.Dispose();
redisConnection = null;