ASP.NET Core의 HybridCache 라이브러리
Important
HybridCache
는 현재 미리 보기 상태이지만 .NET 확장의 향후 부 릴리스에서 .NET 9.0 이후 완전히 릴리스될 예정입니다.
이 문서에서는 ASP.NET Core 앱에서 라이브러리를 HybridCache
구성하고 사용하는 방법을 설명합니다. 라이브러리에 대한 소개는 캐싱 개요 섹션을 참조 HybridCache
하세요.
라이브러리 가져오기
Microsoft.Extensions.Caching.Hybrid
패키지를 설치합니다.
dotnet add package Microsoft.Extensions.Caching.Hybrid --version "9.0.0-preview.7.24406.2"
서비스 등록
다음을 HybridCache
호출AddHybridCache
하여 DI(종속성 주입) 컨테이너에 서비스를 추가합니다.
// Add services to the container.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddAuthorization();
builder.Services.AddHybridCache();
위의 코드는 기본 옵션으로 서비스를 등록합니다 HybridCache
. 등록 API는 옵션 및 serialization을 구성할 수도 있습니다.
캐시 항목 가져오기 및 저장
이 HybridCache
서비스는 키를 사용하고 다음 두 오버로드가 있는 메서드를 제공합니다 GetOrCreateAsync
.
- 팩터리 메서드입니다.
- 상태 및 팩터리 메서드입니다.
메서드는 키를 사용하여 기본 캐시에서 개체를 검색하려고 합니다. 기본 캐시(캐시 누락)에서 항목을 찾을 수 없는 경우 보조 캐시가 구성되어 있는지 확인합니다. 데이터가 없는 경우(다른 캐시 누락) 팩터리 메서드를 호출하여 데이터 원본에서 개체를 가져옵니다. 그런 다음 기본 및 보조 캐시에 개체를 저장합니다. 개체가 주 또는 보조 캐시(캐시 적중)에 있으면 팩터리 메서드가 호출되지 않습니다.
이 HybridCache
서비스는 지정된 키에 대한 동시 호출자 하나만 팩터리 메서드를 호출하고 다른 모든 호출자는 해당 호출 결과를 기다립니다. 전달된 GetOrCreateAsync
값은 CancellationToken
모든 동시 호출자의 결합된 취소를 나타냅니다.
주 GetOrCreateAsync
오버로드
대부분의 시나리오에서는 상태 비스테이스 오버로드 GetOrCreateAsync
를 사용하는 것이 좋습니다. 호출하는 코드는 비교적 간단합니다. 예를 들어 다음과 같습니다.
public class SomeService(HybridCache cache)
{
private HybridCache _cache = cache;
public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
{
return await _cache.GetOrCreateAsync(
$"{name}-{id}", // Unique key to the cache entry
async cancel => await GetDataFromTheSourceAsync(name, id, cancel),
cancellationToken: token
);
}
public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
{
string someInfo = $"someinfo-{name}-{id}";
return someInfo;
}
}
대체 GetOrCreateAsync
오버로드
대체 오버로드는 캡처된 변수 및 인스턴스별 콜백에서 약간의 오버헤드를 줄일 수 있지만, 더 복잡한 코드를 희생할 수 있습니다. 대부분의 시나리오에서 성능 향상은 코드 복잡성보다 크지 않습니다. 대체 오버로드를 사용하는 예제는 다음과 같습니다.
public class SomeService(HybridCache cache)
{
private HybridCache _cache = cache;
public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
{
return await _cache.GetOrCreateAsync(
$"{name}-{id}", // Unique key to the cache entry
(name, id, obj: this),
static async (state, token) =>
await state.obj.GetDataFromTheSourceAsync(state.name, state.id, token),
cancellationToken: token
);
}
public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
{
string someInfo = $"someinfo-{name}-{id}";
return someInfo;
}
}
SetAsync
메서드
많은 시나리오 GetOrCreateAsync
에서 필요한 유일한 API입니다. SetAsync
그러나 HybridCache
개체를 먼저 검색하지 않고 캐시에 저장해야 합니다.
키별 캐시 항목 제거
캐시 항목의 기본 데이터가 만료되기 전에 변경되는 경우 항목에 대한 키를 사용하여 호출 RemoveAsync
하여 항목을 명시적으로 제거합니다. 오버로드를 사용하면 키 값 컬렉션을 지정할 수 있습니다.
항목이 제거되면 주 캐시와 보조 캐시에서 모두 제거됩니다.
태그로 캐시 항목 제거
태그를 사용하여 캐시 항목을 그룹화하고 함께 무효화할 수 있습니다.
다음 예제와 같이 호출 GetOrCreateAsync
할 때 태그를 설정합니다.
public class SomeService(HybridCache cache)
{
private HybridCache _cache = cache;
public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
{
var tags = new List<string> { "tag1", "tag2", "tag3" };
var entryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromMinutes(1),
LocalCacheExpiration = TimeSpan.FromMinutes(1)
};
return await _cache.GetOrCreateAsync(
$"{name}-{id}", // Unique key to the cache entry
async cancel => await GetDataFromTheSourceAsync(name, id, cancel),
entryOptions,
tags,
cancellationToken: token
);
}
public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
{
string someInfo = $"someinfo-{name}-{id}";
return someInfo;
}
}
태그 값을 사용하여 호출 RemoveByTagAsync
하여 지정된 태그에 대한 모든 항목을 제거합니다. 오버로드를 사용하면 태그 값 컬렉션을 지정할 수 있습니다.
항목이 제거되면 주 캐시와 보조 캐시에서 모두 제거됩니다.
옵션
이 메서드를 AddHybridCache
사용하여 전역 기본값을 구성할 수 있습니다. 다음 예제에서는 사용 가능한 옵션 중 일부를 구성하는 방법을 보여줍니다.
// Add services to the container.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization();
builder.Services.AddHybridCache(options =>
{
options.MaximumPayloadBytes = 1024 * 1024;
options.MaximumKeyLength = 1024;
options.DefaultEntryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromMinutes(5),
LocalCacheExpiration = TimeSpan.FromMinutes(5)
};
});
이 메서드는 GetOrCreateAsync
개체를 HybridCacheEntryOptions
사용하여 특정 캐시 항목에 대한 전역 기본값을 재정의할 수도 있습니다. 예를 들어 다음과 같습니다.
public class SomeService(HybridCache cache)
{
private HybridCache _cache = cache;
public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
{
var tags = new List<string> { "tag1", "tag2", "tag3" };
var entryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromMinutes(1),
LocalCacheExpiration = TimeSpan.FromMinutes(1)
};
return await _cache.GetOrCreateAsync(
$"{name}-{id}", // Unique key to the cache entry
async cancel => await GetDataFromTheSourceAsync(name, id, cancel),
entryOptions,
tags,
cancellationToken: token
);
}
public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
{
string someInfo = $"someinfo-{name}-{id}";
return someInfo;
}
}
옵션에 대한 자세한 내용은 소스 코드를 참조하세요.
제한
다음 속성을 HybridCacheOptions
사용하면 모든 캐시 항목에 적용되는 제한을 구성할 수 있습니다.
- MaximumPayloadBytes - 캐시 항목의 최대 크기입니다. 기본값은 1MB입니다. 이 크기에 대한 값 저장 시도가 기록되고 값이 캐시에 저장되지 않습니다.
- MaximumKeyLength - 캐시 키의 최대 길이입니다. 기본값은 1024자입니다. 이 크기에 대한 값 저장 시도가 기록되고 값이 캐시에 저장되지 않습니다.
직렬화
보조 out-of-process 캐시를 사용하려면 serialization이 필요합니다. 직렬화는 서비스 등록의 일부로 구성됩니다 HybridCache
. 형식별 및 범용 직렬 변환기는 호출에서 연결된 메서드 및 AddSerializerFactory
메서드를 AddHybridCache
통해 AddSerializer
구성할 수 있습니다. 기본적으로 라이브러리는 내부적으로 처리 string
하고 byte[]
다른 모든 항목에 사용합니다 System.Text.Json
. HybridCache
는 protobuf 또는 XML과 같은 다른 직렬 변환기를 사용할 수도 있습니다.
다음 예제에서는 형식별 protobuf 직렬 변환기를 사용하도록 서비스를 구성합니다.
// Add services to the container.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization();
builder.Services.AddHybridCache(options =>
{
options.DefaultEntryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromSeconds(10),
LocalCacheExpiration = TimeSpan.FromSeconds(5)
};
}).AddSerializer<SomeProtobufMessage,
GoogleProtobufSerializer<SomeProtobufMessage>>();
다음 예제에서는 많은 protobuf 형식을 처리할 수 있는 범용 protobuf 직렬 변환기를 사용하도록 서비스를 구성합니다.
// Add services to the container.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization();
builder.Services.AddHybridCache(options =>
{
options.DefaultEntryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromSeconds(10),
LocalCacheExpiration = TimeSpan.FromSeconds(5)
};
}).AddSerializerFactory<GoogleProtobufSerializerFactory>();
보조 캐시에는 Redis 또는 SqlServer와 같은 데이터 저장소가 필요합니다. Azure Cache for Redis를 사용하려면 다음을 수행합니다.
Microsoft.Extensions.Caching.StackExchangeRedis
패키지를 설치합니다.Azure Cache for Redis의 인스턴스를 만듭니다.
Redis 인스턴스에 연결하는 연결 문자열 가져옵니다. Azure Portal의 개요 페이지에서 액세스 키 표시를 선택하여 연결 문자열 찾습니다.
앱의 구성에 연결 문자열 저장합니다. 예를 들어 다음 JSON과 같은 사용자 비밀 파일을 섹션의 연결 문자열
ConnectionStrings
사용합니다. 실제 연결 문자열 바꿉다<the connection string>
.{ "ConnectionStrings": { "RedisConnectionString": "<the connection string>" } }
Redis 패키지가
IDistributedCache
제공하는 구현을 DI에 등록합니다. 이렇게 하려면 호출AddStackExchangeRedisCache
하고 연결 문자열 전달합니다. 예시:builder.Services.AddStackExchangeRedisCache(options => { options.Configuration = builder.Configuration.GetConnectionString("RedisConnectionString"); });
Redis
IDistributedCache
구현은 이제 앱의 DI 컨테이너에서 사용할 수 있습니다.HybridCache
는 보조 캐시로 사용하고 구성된 직렬 변환기를 사용합니다.
자세한 내용은 HybridCache serialization 샘플 앱을 참조 하세요.
캐시 스토리지
기본적으로 HybridCache
기본 캐시 스토리지에 사용됩니다 MemoryCache . 캐시 항목은 프로세스에 저장되므로 각 서버에는 서버 프로세스가 다시 시작될 때마다 손실되는 별도의 캐시가 있습니다. Redis 또는 SQL Server HybridCache
와 같은 보조 Out-of-process 스토리지의 경우 구성된 IDistributedCache
구현(있는 경우)을 사용합니다. 그러나 구현 HybridCache
이 IDistributedCache
없더라도 서비스는 여전히 In-Process 캐싱 및 스탬피드 보호를 제공합니다.
성능 최적화
성능을 최적화하려면 개체를 다시 사용하고 할당을 방지 byte[]
하도록 구성 HybridCache
합니다.
개체 다시 사용
인스턴스 HybridCache
를 다시 사용하면 호출별 역직렬화와 관련된 CPU 및 개체 할당의 오버헤드를 줄일 수 있습니다. 이렇게 하면 캐시된 개체가 크거나 자주 액세스하는 시나리오에서 성능이 향상될 수 있습니다.
사용하는 IDistributedCache
일반적인 기존 코드에서는 캐시에서 개체를 검색할 때마다 역직렬화가 발생합니다. 이 동작은 각 동시 호출자가 다른 인스턴스와 상호 작용할 수 없는 개체의 별도 인스턴스를 가져옵니다. 동일한 개체 인스턴스를 동시에 수정할 위험이 없으므로 스레드 안전성도 발생합니다.
HybridCache
많은 사용량이 기존 IDistributedCache
코드 HybridCache
에서 조정되므로 동시성 버그가 발생하지 않도록 기본적으로 이 동작을 유지합니다. 그러나 다음과 같은 경우 개체는 기본적으로 스레드로부터 안전합니다.
- 변경할 수 없는 형식입니다.
- 코드는 수정하지 않습니다.
이러한 경우 다음을 통해 인스턴스를 다시 사용하는 것이 안전하다는 것을 알릴 HybridCache
수 있습니다.
- 형식을 .로 표시
sealed
합니다. C#의 키워드는sealed
클래스를 상속할 수 없다는 것을 의미합니다. - 형식에
[ImmutableObject(true)]
특성 적용 이 특성은[ImmutableObject(true)]
개체를 만든 후에는 개체의 상태를 변경할 수 없다는 것을 나타냅니다.
할당 방지 byte[]
HybridCache
또한 할당을 방지하기 byte[]
위해 구현에 대한 IDistributedCache
선택적 API를 제공합니다. 이 기능은 미리 보기 버전의 및 Microsoft.Extensions.Caching.SqlServer
패키지에 Microsoft.Extensions.Caching.StackExchangeRedis
의해 구현됩니다. 자세한 내용은 IBufferDistributedCache 패키지를 설치하는 .NET CLI 명령은 다음과 같습니다.
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis --prerelease
dotnet add package Microsoft.Extensions.Caching.SqlServer --prerelease
사용자 지정 HybridCache 구현
추상 클래스의 HybridCache
구체적인 구현은 공유 프레임워크에 포함되며 종속성 주입을 통해 제공됩니다. 그러나 개발자는 API의 사용자 지정 구현을 제공할 수 있습니다.
호환성
라이브러리는 HybridCache
.NET Framework 4.7.2 및 .NET Standard 2.0까지 이전 .NET 런타임을 지원합니다.
추가 리소스
자세한 HybridCache
내용은 다음 리소스를 참조하세요.
- GitHub 이슈 dotnet/aspnetcore #54647.
HybridCache
소스 코드
ASP.NET Core