Библиотека HybridCache в ASP.NET Core
Внимание
HybridCache
в настоящее время по-прежнему находится в предварительной версии, но будет полностью выпущен после .NET 9.0 в будущем дополнительном выпуске расширений .NET.
В этой статье объясняется, как настроить и использовать библиотеку HybridCache
в приложении ASP.NET Core. Общие сведения о библиотеке см . в HybridCache
разделе обзора кэширования.
Получение библиотеки
Установите пакет Microsoft.Extensions.Caching.Hybrid
.
dotnet add package Microsoft.Extensions.Caching.Hybrid --version "9.0.0-preview.7.24406.2"
Регистрация службы
Добавьте службу в HybridCache
контейнер внедрения зависимостей (DI), вызвав:AddHybridCache
// Add services to the container.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddAuthorization();
builder.Services.AddHybridCache();
Предыдущий код регистрирует HybridCache
службу с параметрами по умолчанию. API регистрации также может настраивать параметры и сериализацию.
Получение и хранение записей кэша
Служба HybridCache
предоставляет GetOrCreateAsync
метод с двумя перегрузками, принимая ключ и:
- Метод фабрики.
- Состояние и метод фабрики.
Метод использует ключ для получения объекта из первичного кэша. Если элемент не найден в основном кэше (отсутствует кэш), он проверяет дополнительный кэш, если он настроен. Если данные отсутствуют (еще один кэш отсутствует), он вызывает метод фабрики, чтобы получить объект из источника данных. Затем он сохраняет объект как в первичных, так и вторичных кэшах. Метод фабрики никогда не вызывается, если объект найден в первичном или вторичном кэше (попадание кэша).
Служба HybridCache
гарантирует, что только один одновременный вызывающий объект для заданного ключа вызывает метод фабрики, а все остальные вызывающие ожидают результата этого вызова. Переданная CancellationToken
функция GetOrCreateAsync
представляет объединенную отмену всех одновременных вызывающих объектов.
Основная 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. Но HybridCache
также необходимо SetAsync
сохранить объект в кэше, не пытаясь сначала получить его.
Удаление записей кэша по ключу
Когда базовые данные для записи кэша изменяются до истечения срока действия, удалите запись явным образом, вызвав 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 — максимальный размер записи кэша. Значение по умолчанию — 1 МБ. Попытки сохранить значения по этому размеру регистрируются, и значение не хранится в кэше.
- MaximumKeyLength — максимальная длина ключа кэша. Значение по умолчанию — 1024 символов. Попытки сохранить значения по этому размеру регистрируются, и значение не хранится в кэше.
Сериализация
Использование вторичного внепроцессного кэша требует сериализации. Сериализация настраивается как часть регистрации HybridCache
службы. Сериализаторы типа и сериализаторы общего назначения можно настроить с помощью AddSerializer
методов и AddSerializerFactory
методов, связанных с вызовом AddHybridCache
. По умолчанию библиотека обрабатывает 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 для Redis, выполните приведенные ниже действия.
Установите пакет
Microsoft.Extensions.Caching.StackExchangeRedis
.Создайте экземпляр Кэш Azure для Redis.
Получите строка подключения, которая подключается к экземпляру Redis. Найдите строка подключения, выбрав "Показать ключи доступа" на странице "Обзор" в портал Azure.
Сохраните строка подключения в конфигурации приложения. Например, используйте файл секретов пользователя, который выглядит как следующий JSON, с строка подключения в
ConnectionStrings
разделе. Замените<the connection string>
фактическим строка подключения:{ "ConnectionStrings": { "RedisConnectionString": "<the connection string>" } }
Зарегистрируйтесь в di
IDistributedCache
реализации, которую предоставляет пакет Redis. Для этого вызовите и передайтеAddStackExchangeRedisCache
строка подключения. Например:builder.Services.AddStackExchangeRedisCache(options => { options.Configuration = builder.Configuration.GetConnectionString("RedisConnectionString"); });
Реализация Redis
IDistributedCache
теперь доступна из контейнера DI приложения.HybridCache
использует его в качестве дополнительного кэша и использует сериализатор, настроенный для него.
Дополнительные сведения см. в примере приложения для сериализации HybridCache.
Хранилище кэша
По умолчанию HybridCache
используется MemoryCache для основного хранилища кэша. Записи кэша хранятся в процессе, поэтому каждый сервер имеет отдельный кэш, который теряется при перезапуске процесса сервера. Для дополнительного внепроцессного хранилища, например Redis или SQL Server, HybridCache
использует настроенную IDistributedCache
реализацию, если она есть. Но даже без реализации HybridCache
служба по-прежнему обеспечивает встроенную IDistributedCache
кэширование и защиту от меток.
Оптимизация производительности
Чтобы оптимизировать производительность, настройте HybridCache
повторное использование объектов и избегайте byte[]
выделения.
Повторное использование объектов
Повторно используя экземпляры, можно сократить затраты на выделение ЦП и объектов, HybridCache
связанных с десериализацией каждого вызова. Это может привести к улучшению производительности в сценариях, когда кэшированные объекты являются большими или часто доступны.
В типичном существующем коде, который использует IDistributedCache
, каждый извлечение объекта из кэша приводит к десериализации. Это означает, что каждый одновременный вызывающий объект получает отдельный экземпляр объекта, который не может взаимодействовать с другими экземплярами. Результатом является безопасность потоков, так как не существует риска параллельных изменений в одном экземпляре объекта.
Так как много HybridCache
использования будет адаптировано из существующего IDistributedCache
кода, сохраняет это поведение по умолчанию, HybridCache
чтобы избежать возникновения ошибок параллелизма. Однако объекты по сути являются потокобезопасными, если:
- Они являются неизменяемыми типами.
- Код не изменяет их.
В таких случаях сообщите HybridCache
, что можно повторно использовать экземпляры следующим образом:
- Пометка типа как
sealed
. Ключевоеsealed
слово в C# означает, что класс не может быть унаследован. - Применение атрибута
[ImmutableObject(true)]
к типу. Атрибут[ImmutableObject(true)]
указывает, что состояние объекта невозможно изменить после его создания.
Избегайте byte[]
выделения
HybridCache
также предоставляет необязательные API для IDistributedCache
реализаций, чтобы избежать byte[]
выделения. Эта функция реализуется предварительными версиями и Microsoft.Extensions.Caching.SqlServer
пакетамиMicrosoft.Extensions.Caching.StackExchangeRedis
. Дополнительные сведения см. в разделе IBufferDistributedCache Ниже приведены команды интерфейса командной строки .NET для установки пакетов:
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis --prerelease
dotnet add package Microsoft.Extensions.Caching.SqlServer --prerelease
Пользовательские реализации HybridCache
Конкретная реализация абстрактного HybridCache
класса включается в общую платформу и предоставляется с помощью внедрения зависимостей. Но разработчики могут предоставлять пользовательские реализации API.
Совместимость
Библиотека HybridCache
поддерживает старые среды выполнения .NET до платформа .NET Framework 4.7.2 и .NET Standard 2.0.
Дополнительные ресурсы
Дополнительные сведения см HybridCache
. в следующих ресурсах:
- Проблема GitHub dotnet/aspnetcore #54647.
- Исходный код
HybridCache
ASP.NET Core