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に接続するためのアクセスキーを取得します。

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ファイルに追加します。

手順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活用の一助となれば幸いです。
-
データベースレス(DBLess)アーキテクチャとは?ファーストプリンシプル思考で読み解くデータベースの未来
「なぜRedisのようなデータベース企業が、Databaseless(DBLess:データベースレス)アーキテクチャについて語るのだろう?」——そう疑問に感じるのは自然なことです。まずは細部に入る前に、このまったく新しいアーキテクチャの背景にある「新しい考え方」から見ていきましょう。 そのために、少しだけ回り道をして「ファーストプリンシプル(第一原理)思考」についてお話しします。この思考法は、伝統や慣習を鵜呑みにせず、自らの頭で考え、あらゆるものに疑問を投げかけることを促すものです。 ファーストプリンシプルの核心はこうです。重力の法則のような自然法則でない限り、あらゆるシステムや概念は人間
-
【Redis入門】RPOPLPUSH・BRPOPLPUSHコマンドでリスト間に要素を移動する方法
このチュートリアルでは、Redisデータストアにおいて、あるキーに保存されたリストの末尾から要素を取り出して返し、その要素を別のキーに保存されたリストの先頭に挿入する方法を解説します。この操作には、RedisのRPOPLPUSHおよびBRPOPLPUSHコマンドを使用します。 RPOPLPUSHコマンドとは RPOPLPUSHコマンドは、ソースキーに格納されたリストの末尾(テール)から要素を取り出して返し、その同じ要素を宛先キーに格納されたリストの先頭(ヘッド)に挿入します。 ソースキーが存在しない場合: nilが返され、何も操作は行われません。 宛先キーが存在しない場合: 挿入操作を実行す