Поделиться через


Библиотека 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. в следующих ресурсах: