Skip to content

MS_ASPNETCoreDistributedCache

nishi_74322014 edited this page Aug 21, 2026 · 1 revision

ASP.NET Coreの分散キャッシュ

概要

昔で言う、StateServer や SQL Serverのモード。

補足(対応関係): ASP.NET Session
セッション状態モードとの対応を整理しておく。

ASP.NET のモード ASP.NET Core の対応 登録メソッド
InProc メモリ内(既定) AddDistributedMemoryCache()
StateServer Redis AddStackExchangeRedisCache()
SQLServer SQL Server AddDistributedSqlServerCache()
Custom 任意の IDistributedCache 実装 自作

重要な違いは、ASP.NET Core では
IDistributedCache という 1 つの抽象に統一されている点である。

【ASP.NET】  セッション専用のプロバイダー機構
【ASP.NET Core】
     IDistributedCache(汎用キャッシュの抽象)
       └─ その利用者の 1 つとして Session がある

このため、セッション以外の用途(アプリ キャッシュ)にも同じ物を使える

抽象 範囲 用途
IMemoryCache 1 プロセス内 高速。マスタ データ等
IDistributedCache 複数台で共有 セッション、共有キャッシュ
HybridCache(.NET 9) 両方を 2 段で L1(メモリ)+ L2(分散)

AddDistributedMemoryCache() は「分散」という名前だが
プロセス内メモリ
である点に注意する
(インターフェイスを揃えるための実装で、複数台では共有されない)。

詳細

Redis

Redis が一般的

サンプル

.NET Core 2.1 以前のバージョンでは、AddDistributedRedisCache を、
.NET Core 2.2 以降のバージョンでは、AddStackExchangeRedisCache を使う。

  • NuGet

    • StackExchange.Redis
    • Microsoft.Extensions.Caching.StackExchangeRedis
    • Microsoft.AspNetCore.DataProtection.StackExchangeRedis
  • コード

using StackExchange.Redis;
using Microsoft.AspNetCore.DataProtection;

...

var redis = ConnectionMultiplexer
    .Connect(Environment.GetEnvironmentVariable("REDIS"));
services
    .AddDataProtection()
    .PersistKeysToStackExchangeRedis(redis, "DataProtectionKeys");
services.AddStackExchangeRedisCache(option =>
{
    option.Configuration = Environment
        .GetEnvironmentVariable("REDIS");
    option.InstanceName = "RedisInstance";
});

補足(このサンプルの要点): 短いコードだが、
複数台構成に必要な 2 つが両方入っている点が重要である。

① PersistKeysToStackExchangeRedis   … データ保護キーの共有
      → Cookie を全台で復号できるようにする

② AddStackExchangeRedisCache        … セッション データの共有
      → セッションの中身を全台で読めるようにする

①を忘れると、②だけ入れても動かない
ASP.NET Coreのデータ保護)。
原文がこの 2 つを 1 つのサンプルにまとめているのは的確である。

SetApplicationName も必要なので、実運用では次の形になる。

var builder = WebApplication.CreateBuilder(args);
var redisConn = builder.Configuration.GetConnectionString("Redis");
var redis = await ConnectionMultiplexer.ConnectAsync(redisConn);

// ① データ保護キーを共有
builder.Services.AddDataProtection()
    .SetApplicationName("MyApp")                       // ← 全台で同じ
    .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");

// ② 分散キャッシュ
builder.Services.AddStackExchangeRedisCache(o =>
{
    o.Configuration  = redisConn;
    o.InstanceName   = "MyApp:";                       // キーの前置き
});

// ③ セッション(②を保存先として使う)
builder.Services.AddSession(o =>
{
    o.IdleTimeout = TimeSpan.FromMinutes(30);
    o.Cookie.IsEssential = true;
});

AddDistributedRedisCache は廃止済みである
Microsoft.Extensions.Caching.Redis パッケージごと非推奨)。
原文が述べる通り AddStackExchangeRedisCache を使う。

config

Connect メソッドの引数は config で、ココに、以下のように、
「,」区切りで、色々なオプションを設定可能であるもよう。

ConnectionMultiplexer connection = 
       ConnectionMultiplexer.Connect("endpoint,password=password,ConnectTimeout=10000");

補足(実務で指定することが多いオプション):

オプション 用途
ssl=true マネージド Redis はほぼ必須(Azure Cache for Redis 等)
abortConnect=false 起動時に Redis が未起動でも落とさない(後で再接続)
connectTimeout / syncTimeout タイムアウト(既定 5000ms)
connectRetry 接続リトライ回数
defaultDatabase 使用する DB 番号
myredis.redis.cache.windows.net:6380,password=xxx,ssl=True,abortConnect=False

abortConnect=false はコンテナ環境でほぼ必須である
(アプリと Redis の起動順が保証されないため)。

なお、接続文字列にパスワードを直書きしないこと。
.NET Core config の構成プロバイダー
(環境変数、ユーザー シークレット、Key Vault)から読み込む。

// ConnectionMultiplexer は「1 アプリに 1 つ」を共有する(Singleton)
builder.Services.AddSingleton<IConnectionMultiplexer>(
    _ => ConnectionMultiplexer.Connect(redisConn));

ConnectionMultiplexer を毎回 new しないのが定石である
(内部で接続を多重化するため、使い回すことが前提の設計)。

  • 昔で言う、machine.config の machineKey の話。

  • 前述のサンプル・コードのように、

    • AddDataProtection()
    • SetApplicationName()
    • PersistKeysToStackExchangeRedis()

を呼び出す。

補足(切り分けの手順): 「複数台にしたらログインが外れる/
セッションが消える」という症状の切り分け順。

① 1 台に固定(スティッキー セッション)すると直るか?
      直る → 共有できていない。②へ

② Redis にセッションのキーが入っているか?
      redis-cli KEYS "MyApp:*"
      入っていない → 分散キャッシュの設定漏れ

③ データ保護キーは共有されているか?
      redis-cli GET "DataProtection-Keys"
      無い → PersistKeysTo* の設定漏れ

④ ApplicationName は全台同じか?
      違う → 鍵束を共有していても別アプリ扱いになる

⑤ ログに CryptographicException / 「キーが見つかりません」が出ていないか

③④ が原因であることが圧倒的に多い

参考

Microsoft Learn

Medium

銀の光と碧い空


Tags: 移行, .NET開発, .NET Core, ASP.NET, ASP.NET MVC

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally