Redis
 Computer >> コンピューター >  >> プログラミング >> Redis

C#でAzure Redis Cacheをマスターする実践ガイド

はじめに

Azure Redis Cacheは、オープンソースのインメモリ型Redisキャッシュを基盤とするサービスです。バックエンドのデータソースからデータをキャッシュに読み込み、キャッシュからWebページを配信することで、アプリケーションのパフォーマンスを大幅に向上させることができます。本記事では、ステップバイステップでC#のWebアプリケーションにAzure Redis Cacheを導入する方法を解説します。

Azure Redis Cacheとは?

現代のアプリケーションの多くは大量のデータを扱います。データベースからデータを取得する際、通常は対象のテーブルを検索し、その結果をユーザーへ返却します。しかし、リクエストが集中するとパフォーマンスが低下しがちです。そこで、更新頻度の低いデータをキャッシュに保存することで、データベースへのリクエスト数を削減できます。

Redis Cacheはオープンソースのインメモリデータベースであり、Key-Value形式でデータをキャッシュメモリに格納・取得することで、アプリケーションの高速化を実現します。Azure Redis Cacheは、セキュアかつ低レイテンシで高スループットなアクセスを提供する多機能なサービスです。

それでは、C#によるRedis Cacheの実装を始めましょう。

手順1:Azureポータルへのログイン

Azureポータルにログインし、「Databases」→「Redis Cache」の順に移動します。

手順2:新しいRedis Cacheの作成

新しいRedis Cacheインスタンスを作成します。

手順3:アクセスキーの取得

作成したRedis Cacheに接続するためのアクセスキーを取得します。

C#でAzure Redis Cacheをマスターする実践ガイド

StackExchange.Redisのインストール

手順4. 次のコマンドを実行して、StackExchange.Redis NuGetパッケージをインストールします。

Install-Package StackExchange.Redis

それでは、Redis Cacheへのデータ保存と取得を行うコードを書いていきましょう。以前の記事でAzure Document DBのCRUD操作コードを紹介しました。まだお読みでない方は、「Azure Document DB CRUD Operation」の記事をご確認ください。Document DBのCRUD操作コードをもとに、ここにRedis Cacheを実装していきます。

手順5. 前回の記事と同様に、Redis Cacheの接続文字列をappsettings.dev.jsonファイルに追加します。

C#でAzure Redis Cacheをマスターする実践ガイド

手順6. 次に、Config.csにRedisCacheプロパティを追加し、appsettings.dev.jsonからRedis Cache接続文字列の値を取得できるようにします。

public class Config
{
    public DocDbConnectionString docDb { get; set; }
    public string RedisCache { get; set; }
}

public class DocDbConnectionString
{
    public string EndPoint { get; set; }
    public string AuthKey { get; set; }
    public string Database { get; set; }
    public string Collection { get; set; }
}

手順7. Program.csファイルに移動し、Redis Cache用のConnectionMultiplexerを追加します。

IDatabase cache = lazyConnection.Value.GetDatabase();

private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
    string cacheConnection = configs.RedisCache;
    return ConnectionMultiplexer.Connect(cacheConnection);
});

public static ConnectionMultiplexer Connection
{
    get
    {
        return lazyConnection.Value;
    }
}

ここからは、Document DBにドキュメントを作成する際に、Keyを基準としてRedis Cacheにも同じドキュメントを保存します。ドキュメントを読み取る際には、まずKeyを使ってRedis Cacheに対象ドキュメントが存在するかを確認し、存在すればDocument DBからの読み取りをスキップします。これにより、アプリケーションのパフォーマンスを向上させることができます。

var collection = UriFactory.CreateDocumentCollectionUri(configs.docDb.Database, configs.docDb.Collection);
try
{
    // 従業員情報を含むJObjectを作成
    Console.WriteLine("\nCreating document");
    JObject emp = new JObject();
    emp.Add("id", "V003");
    emp.Add("name", "virendra");
    emp.Add("address", "Indore");
    emp.Add("Country", "India");

    // Document DBにドキュメントを作成
    var createResponse = await Client.CreateDocumentAsync(collection, emp);
    var createdDocument = createResponse.Resource;
    Console.WriteLine("Document with id {0} created", createdDocument.Id);

    // "redisEmp3"というキーでJObjectをRedis Cacheに保存
    var entryInRedis = await cache.StringSetAsync("redisEmp3", emp.ToString());
    Console.WriteLine("Document with key redisEmp3 stored into redis cache");
}
catch (Exception ex)
{
    throw ex;
}

手順8. 今度は、Redis Cacheからドキュメントを読み取ります。

// Redis Cacheからドキュメントを読み込む
var empInRedis = await cache.StringGetAsync("redisEmp3");
if (!empInRedis.IsNullOrEmpty)
{
    Console.WriteLine("Read Document from RedisCache {0} : ", empInRedis);
}

// Redis Cacheにドキュメントが存在しない場合はDocument DBから読み込む
if (empInRedis.IsNullOrEmpty)
{
    var readResponse = await client.ReadDocumentAsync(UriFactory.CreateDocumentUri(configs.docDb.Database, configs.docDb.Collection, "V001"));
    var readDocument = readResponse.Resource;
    Console.WriteLine("Read Document {0}: ", readResponse.Resource.ToString());
}

以下のスクリーンショットは、Redis Cacheからドキュメントを読み取る様子を示しています。

手順9. Program.csクラスの完全なコードは以下の通りです。

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq;
using StackExchange.Redis;
using Microsoft.Azure.Documents.Client;

public class Program
{
    private static IConfiguration Configuration { get; set; }
    private static Config configs;
    private DocumentClient client;
    private IDatabase cache = lazyConnection.Value.GetDatabase();

    static void Main(string[] args)
    {
        // 構成のセットアップ
        var builder = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: false, reloadOnChange: true);
        Configuration = builder.Build();
        configs = new Config();
        Configuration.Bind(configs);

        Program obj = new Program();
        obj.CRUDOperation().Wait();
    }

    // CRUD操作
    private async Task CRUDOperation()
    {
        var collection = UriFactory.CreateDocumentCollectionUri(configs.docDb.Database, configs.docDb.Collection);
        try
        {
            // 従業員情報を含むJObjectを作成
            Console.WriteLine("\nCreating document");
            JObject emp = new JObject();
            emp.Add("id", "V003");
            emp.Add("name", "virendra");
            emp.Add("address", "Indore");
            emp.Add("Country", "India");

            // ドキュメントを作成
            var createResponse = await Client.CreateDocumentAsync(collection, emp);
            var createdDocument = createResponse.Resource;
            Console.WriteLine("Document with id {0} created", createdDocument.Id);

            // "redisEmp3"というキーでJObjectをRedis Cacheに保存
            var entryInRedis = await cache.StringSetAsync("redisEmp3", emp.ToString());
            Console.WriteLine("Document with key redisEmp3 stored into redis cache");
        }
        catch (Exception ex)
        {
            throw ex;
        }

        // Redis Cacheからドキュメントを読み込む
        var empInRedis = await cache.StringGetAsync("redisEmp3");
        if (!empInRedis.IsNullOrEmpty)
        {
            Console.WriteLine("Read Document from RedisCache {0} : ", empInRedis);
        }

        if (empInRedis.IsNullOrEmpty)
        {
            // Document DBからドキュメントを読み込む
            var readResponse = await client.ReadDocumentAsync(UriFactory.CreateDocumentUri(configs.docDb.Database, configs.docDb.Collection, "V001"));
            var readDocument = readResponse.Resource;
            Console.WriteLine("Read Document {0}: ", readResponse.Resource.ToString());
        }
    }

    // DocumentClientのシングルトンインスタンスを取得して再利用
    public DocumentClient Client
    {
        get
        {
            if (client == null)
            {
                Uri endpointUri = new Uri(configs.docDb.EndPoint);
                client = new DocumentClient(endpointUri, configs.docDb.AuthKey, null, ConsistencyLevel.Session);
                client.OpenAsync();
            }
            return client;
        }
    }

    // Redis Cache接続の確立
    private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
    {
        string cacheConnection = configs.RedisCache;
        return ConnectionMultiplexer.Connect(cacheConnection);
    });

    public static ConnectionMultiplexer Connection
    {
        get
        {
            return lazyConnection.Value;
        }
    }
}

本記事が、C#でのAzure Redis Cache活用の一助となれば幸いです。

  1. データベースレス(DBLess)アーキテクチャとは?ファーストプリンシプル思考で読み解くデータベースの未来

    「なぜRedisのようなデータベース企業が、Databaseless(DBLess:データベースレス)アーキテクチャについて語るのだろう?」——そう疑問に感じるのは自然なことです。まずは細部に入る前に、このまったく新しいアーキテクチャの背景にある「新しい考え方」から見ていきましょう。 そのために、少しだけ回り道をして「ファーストプリンシプル(第一原理)思考」についてお話しします。この思考法は、伝統や慣習を鵜呑みにせず、自らの頭で考え、あらゆるものに疑問を投げかけることを促すものです。 ファーストプリンシプルの核心はこうです。重力の法則のような自然法則でない限り、あらゆるシステムや概念は人間

  2. 【Redis入門】RPOPLPUSH・BRPOPLPUSHコマンドでリスト間に要素を移動する方法

    このチュートリアルでは、Redisデータストアにおいて、あるキーに保存されたリストの末尾から要素を取り出して返し、その要素を別のキーに保存されたリストの先頭に挿入する方法を解説します。この操作には、RedisのRPOPLPUSHおよびBRPOPLPUSHコマンドを使用します。 RPOPLPUSHコマンドとは RPOPLPUSHコマンドは、ソースキーに格納されたリストの末尾(テール)から要素を取り出して返し、その同じ要素を宛先キーに格納されたリストの先頭(ヘッド)に挿入します。 ソースキーが存在しない場合: nilが返され、何も操作は行われません。 宛先キーが存在しない場合: 挿入操作を実行す