Бөлісу құралы:


Распределенное кэширование в ASP.NET Core

Mohsin Nasir и smandia

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.

Предупреждение

Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в статье о политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 8 этой статьи.

Внимание

Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

В текущем выпуске см . версию .NET 8 этой статьи.

Распределенный кэш — это кэш, совместно используемый несколькими серверами приложений, как правило, в качестве внешней службы для серверов приложений, к которым он обращается. Распределенный кэш может повысить производительность и масштабируемость приложения ASP.NET Core, особенно если приложение размещается облачной службой или фермой серверов.

Распределенный кэш имеет несколько преимуществ по сравнению с другими сценариями кэширования, в которых кэшированные данные хранятся на отдельных серверах приложений.

При распределении кэшированных данных данные:

  • Последовательный (согласованный) между запросами на несколько серверов.
  • Выживает перезапуски сервера и развертывания приложений.
  • Не использует локальную память.

Конфигурация распределенного кэша является конкретной реализацией. В этой статье описывается настройка распределенных кэшей SQL Server и Redis. Кроме того, доступны сторонние реализации, такие как NCache (NCache на GitHub). Независимо от выбранной реализации приложение взаимодействует с кэшем с помощью IDistributedCache интерфейса.

Просмотреть или скачать образец кода (описание загрузки)

Предупреждение

В этой статье используется локальная база данных, которая не требует проверки подлинности пользователя. Рабочие приложения должны использовать самый безопасный поток проверки подлинности. Дополнительные сведения о проверке подлинности для развернутых тестовых и рабочих приложений см. в разделе "Безопасные потоки проверки подлинности".

Необходимые компоненты

Добавьте ссылку на пакет для используемого поставщика распределенного кэша:

Интерфейс IDistributedCache

Интерфейс IDistributedCache предоставляет следующие методы для управления элементами в реализации распределенного кэша:

  • Get: GetAsyncпринимает строковый ключ и извлекает кэшированный элемент в виде byte[] массива, если он найден в кэше.
  • Set, SetAsync: добавляет элемент (в виде byte[] массива) в кэш с помощью строкового ключа.
  • Refresh, RefreshAsync: обновляет элемент в кэше на основе ключа, сбросив время ожидания скольжения срока действия (если таковой имеется).
  • Remove, RemoveAsync: удаляет элемент кэша на основе его строкового ключа.

Установка распределенных служб кэширования

Регистрация реализации IDistributedCache в Program.cs. Предоставляемые платформой реализации, описанные в этом разделе, включают:

Распределенный кэш Redis

Мы рекомендуем использовать распределенный кэш Redis для рабочих приложений, так как это наиболее эффективно. Дополнительные сведения см. в разделе "Рекомендации".

Redis -это хранилище данных в памяти с открытым исходным кодом, которое часто используется в качестве распределенного кэша. Вы можете настроить Кэш Azure для Redis для размещенного в Azure приложения ASP.NET Core и использовать Кэш Azure для Redis для локальной разработки.

Приложение настраивает реализацию кэша с помощью экземпляра RedisCache путем вызова AddStackExchangeRedisCache. Для кэширования выходных данных используйте AddStackExchangeRedisOutputCache.

  1. Создайте Кэш Azure для Redis.
  2. Скопируйте основной строка подключения (StackExchange.Redis) в конфигурацию.
    • Локальная разработка. Сохранение строка подключения с помощью диспетчера секретов.
    • Azure: сохранение строка подключения в безопасном хранилище, например Azure Key Vault

Следующий код включает Кэш Azure для Redis:

builder.Services.AddStackExchangeRedisCache(options =>
 {
     options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr");
     options.InstanceName = "SampleInstance";
 });

Предыдущий код предполагает, что основной строка подключения (StackExchange.Redis) был сохранен в конфигурации с именем MyRedisConStrключа.

См. сведения на странице с ценами на Azure Cache for Redis.

См . эту проблему GitHub для обсуждения альтернативных подходов к локальному кэшу Redis.

Кэш распределенной памяти

Кэш распределенной памяти (AddDistributedMemoryCache) — это платформа, предоставляемая платформой, в IDistributedCache которой хранятся элементы в памяти. Кэш распределенной памяти не является фактическим распределенным кэшем. Кэшированные элементы хранятся экземпляром приложения на сервере, на котором выполняется приложение.

Кэш распределенной памяти — это полезная реализация:

  • В сценариях разработки и тестирования.
  • Если один сервер используется в рабочей среде, а потребление памяти не является проблемой. Реализация распределенного кэша памяти абстрагирует кэшированное хранилище данных. Он позволяет реализовать истинное распределенное решение кэширования в будущем, если потребуется несколько узлов или отказоустойчивости.

Пример приложения использует кэш распределенной памяти при запуске приложения в среде разработки в Program.cs:

builder.Services.AddDistributedMemoryCache();

Распределенный кэш SQL Server

Реализация распределенного кэша SQL Server (AddDistributedSqlServerCache) позволяет распределенного кэша использовать базу данных SQL Server в качестве резервного хранилища. Чтобы создать таблицу кэшированных элементов SQL Server в экземпляре SQL Server, можно использовать sql-cache средство. Средство создает таблицу с указанным именем и схемой.

Создайте таблицу в SQL Server, выполнив sql-cache create команду. Укажите экземпляр SQL Server (), базу данных (Data Source), схему (Initial Catalogнапример, dbo) и имя таблицы (например, TestCache):

dotnet sql-cache create "Data Source=(localdb)/MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache

В журнал записывается сообщение, указывающее, что средство выполнено успешно:

Table and index were created successfully.

Таблица, sql-cache созданная средством, имеет следующую схему:

Таблица кэша SqlServer

Примечание.

Приложение должно управлять значениями кэша с помощью экземпляра IDistributedCache, а не SqlServerCache.

Пример приложения реализуется в среде, отличной от разработки SqlServerCache , в Program.cs:

builder.Services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = builder.Configuration.GetConnectionString(
        "DistCache_ConnectionString");
    options.SchemaName = "dbo";
    options.TableName = "TestCache";
});

Примечание.

A ConnectionStringTableNameнеобязательно) SchemaName обычно хранятся вне системы управления версиями (например, хранятся в диспетчере секретов или в appsettings.json/appsettings.{Environment}.json файлах). Строка подключения может содержать учетные данные, которые должны храниться вне систем управления версиями.

Распределенный кэш NCache

NCache — это открытый код распределенный кэш в памяти, разработанный изначально в .NET и .NET Core. NCache работает как локально, так и настроен как кластер распределенного кэша для приложения ASP.NET Core, работающего в Azure или на других платформах размещения.

Сведения об установке и настройке NCache на локальном компьютере см. в руководстве по началу работы с Windows (.NET и .NET Core).

Чтобы настроить NCache, выполните приведенные действия.

  1. Установите NCache открытый код NuGet.
  2. Настройте кластер кэша в client.ncconf.
  3. Добавьте следующий код в Program.cs:
builder.Services.AddNCacheDistributedCache(configuration =>
{
    configuration.CacheName = "democache";
    configuration.EnableLogs = true;
    configuration.ExceptionsEnabled = true;
});

Распределенный кэш Azure CosmosDB

Azure Cosmos DB можно использовать в ASP.NET Core в качестве поставщика состояний сеанса IDistributedCache с помощью интерфейса. Azure Cosmos DB — это полностью управляемая база данных NoSQL и реляционная база данных для современной разработки приложений, которая обеспечивает высокий уровень доступности, масштабируемость и низкую задержку доступа к данным для критически важных приложений.

После установки пакета NuGet Microsoft.Extensions.Caching.Cosmos настройте распределенный кэш Azure Cosmos DB следующим образом:

Повторное использование существующего клиента

Самый простой способ настройки распределенного кэша — повторно использовать существующий клиент Azure Cosmos DB. В этом случае CosmosClient экземпляр не будет удален при удалении поставщика.

services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
{
    cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
    cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
    cacheOptions.CosmosClient = existingCosmosClient;
    cacheOptions.CreateIfNotExists = true;
});

Создание нового клиента

Кроме того, создайте экземпляр нового клиента. В этом случае CosmosClient экземпляр будет удален при удалении поставщика.

services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
{
    cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
    cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
    cacheOptions.ClientBuilder = new CosmosClientBuilder(Configuration["CosmosConnectionString"]);
    cacheOptions.CreateIfNotExists = true;
});

Использование распределенного кэша

Чтобы использовать IDistributedCache интерфейс, запросите экземпляр IDistributedCache приложения. Экземпляр предоставляется внедрением зависимостей (DI).

При запуске IDistributedCache примера приложения вставляется в Program.cs. Текущее время кэшируется с помощью IHostApplicationLifetime (дополнительные сведения см. в разделе Generic Host: IHostApplicationLifetime):

app.Lifetime.ApplicationStarted.Register(() =>
{
    var currentTimeUTC = DateTime.UtcNow.ToString();
    byte[] encodedCurrentTimeUTC = System.Text.Encoding.UTF8.GetBytes(currentTimeUTC);
    var options = new DistributedCacheEntryOptions()
        .SetSlidingExpiration(TimeSpan.FromSeconds(20));
    app.Services.GetService<IDistributedCache>()
                              .Set("cachedTimeUTC", encodedCurrentTimeUTC, options);
});

Пример приложения внедряется IDistributedCache на IndexModel страницу индекса.

Каждый раз при загрузке страницы индекса кэш проверяется на время кэширования.OnGetAsync Если кэшированное время не истекло, отображается время. Если 20 секунд истекло с момента последнего доступа к кэшированному времени (время последней загрузки этой страницы), на странице отображается срок действия кэшированного времени.

Немедленно обновите кэшированное время до текущего времени, нажав кнопку "Сброс кэшированного времени ". Кнопка активирует метод обработчика OnPostResetCachedTime .

public class IndexModel : PageModel
{
    private readonly IDistributedCache _cache;

    public IndexModel(IDistributedCache cache)
    {
        _cache = cache;
    }

    public string? CachedTimeUTC { get; set; }
    public string? ASP_Environment { get; set; }

    public async Task OnGetAsync()
    {
        CachedTimeUTC = "Cached Time Expired";
        var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");

        if (encodedCachedTimeUTC != null)
        {
            CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
        }

        ASP_Environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        if (String.IsNullOrEmpty(ASP_Environment))
        {
            ASP_Environment = "Null, so Production";
        }
    }

    public async Task<IActionResult> OnPostResetCachedTime()
    {
        var currentTimeUTC = DateTime.UtcNow.ToString();
        byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
        var options = new DistributedCacheEntryOptions()
            .SetSlidingExpiration(TimeSpan.FromSeconds(20));
        await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);

        return RedirectToPage();
    }
}

Нет необходимости использовать одноэлементное или ограниченное время существования для IDistributedCache экземпляров со встроенными реализациями.

Вы также можете создать IDistributedCache экземпляр, где бы вам ни понадобилось, а не использовать di, но создание экземпляра в коде может сделать код сложнее тестировать и нарушать принцип явных зависимостей.

Рекомендации

При принятии решения о том, какая реализация IDistributedCache лучше всего подходит для вашего приложения, рассмотрите следующее:

  • Существующая инфраструктура
  • Требования к производительности
  • Себестоимость
  • Взаимодействие с командой

Решения кэширования обычно полагаются на хранилище в памяти для быстрого извлечения кэшированных данных, но память является ограниченным ресурсом и дорогостоящим для расширения. В кэше хранятся только часто используемые данные.

Для большинства приложений кэш Redis обеспечивает более высокую пропускную способность и низкую задержку, чем кэш SQL Server. Однако для определения характеристик производительности стратегий кэширования рекомендуется использовать тестовые показатели.

Если SQL Server используется в качестве хранилища резервной копии распределенного кэша, использование одной базы данных для кэша и обычного хранилища данных приложения и извлечения может негативно повлиять на производительность обоих. Рекомендуется использовать выделенный экземпляр SQL Server для хранилища серверной части распределенного кэша.

Дополнительные ресурсы

Распределенный кэш — это кэш, совместно используемый несколькими серверами приложений, как правило, в качестве внешней службы для серверов приложений, к которым он обращается. Распределенный кэш может повысить производительность и масштабируемость приложения ASP.NET Core, особенно если приложение размещается облачной службой или фермой серверов.

Распределенный кэш имеет несколько преимуществ по сравнению с другими сценариями кэширования, в которых кэшированные данные хранятся на отдельных серверах приложений.

При распределении кэшированных данных данные:

  • Последовательный (согласованный) между запросами на несколько серверов.
  • Выживает перезапуски сервера и развертывания приложений.
  • Не использует локальную память.

Конфигурация распределенного кэша является конкретной реализацией. В этой статье описывается настройка распределенных кэшей SQL Server и Redis. Кроме того, доступны сторонние реализации, такие как NCache (NCache на GitHub). Независимо от выбранной реализации приложение взаимодействует с кэшем с помощью IDistributedCache интерфейса.

Просмотреть или скачать образец кода (описание загрузки)

Необходимые компоненты

Добавьте ссылку на пакет для используемого поставщика распределенного кэша:

  • Для распределенного кэша Redis microsoft.Extensions.Caching.StackExchangeRedis.

  • Для SQL Server, Microsoft.Extensions.Caching.SqlServer.

  • Для распределенного кэша NCache. NCache.Microsoft.Extensions.Caching.OpenSource.

  • Предупреждение

    В этой статье используется локальная база данных, которая не требует проверки подлинности пользователя. Рабочие приложения должны использовать самый безопасный поток проверки подлинности. Дополнительные сведения о проверке подлинности для развернутых тестовых и рабочих приложений см. в разделе "Безопасные потоки проверки подлинности".

Интерфейс IDistributedCache

Интерфейс IDistributedCache предоставляет следующие методы для управления элементами в реализации распределенного кэша:

  • Get: GetAsyncпринимает строковый ключ и извлекает кэшированный элемент в виде byte[] массива, если он найден в кэше.
  • Set, SetAsync: добавляет элемент (в виде byte[] массива) в кэш с помощью строкового ключа.
  • Refresh, RefreshAsync: обновляет элемент в кэше на основе ключа, сбросив время ожидания скольжения срока действия (если таковой имеется).
  • Remove, RemoveAsync: удаляет элемент кэша на основе его строкового ключа.

Установка распределенных служб кэширования

Регистрация реализации IDistributedCache в Program.cs. Предоставляемые платформой реализации, описанные в этом разделе, включают:

Распределенный кэш Redis

Мы рекомендуем использовать распределенный кэш Redis для рабочих приложений, так как это наиболее эффективно. Дополнительные сведения см. в разделе "Рекомендации".

Redis -это хранилище данных в памяти с открытым исходным кодом, которое часто используется в качестве распределенного кэша. Вы можете настроить кэш Redis Azure для размещенного в Azure приложения ASP.NET Core и использовать кэш Redis Azure для локальной разработки.

Приложение настраивает реализацию кэша с помощью экземпляра RedisCache (AddStackExchangeRedisCache).

  1. Создайте Кэш Azure для Redis.
  2. Скопируйте основной строка подключения (StackExchange.Redis) в конфигурацию.
    • Локальная разработка. Сохранение строка подключения с помощью диспетчера секретов.
    • Azure: сохранение строка подключения в безопасном хранилище, например Azure Key Vault

Следующий код включает Кэш Azure для Redis:

builder.Services.AddStackExchangeRedisCache(options =>
 {
     options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr");
     options.InstanceName = "SampleInstance";
 });

Предыдущий код предполагает, что основной строка подключения (StackExchange.Redis) был сохранен в конфигурации с именем MyRedisConStrключа.

См. сведения на странице с ценами на Azure Cache for Redis.

См . эту проблему GitHub для обсуждения альтернативных подходов к локальному кэшу Redis.

Кэш распределенной памяти

Кэш распределенной памяти (AddDistributedMemoryCache) — это платформа, предоставляемая платформой, в IDistributedCache которой хранятся элементы в памяти. Кэш распределенной памяти не является фактическим распределенным кэшем. Кэшированные элементы хранятся экземпляром приложения на сервере, на котором выполняется приложение.

Кэш распределенной памяти — это полезная реализация:

  • В сценариях разработки и тестирования.
  • Если один сервер используется в рабочей среде, а потребление памяти не является проблемой. Реализация распределенного кэша памяти абстрагирует кэшированное хранилище данных. Он позволяет реализовать истинное распределенное решение кэширования в будущем, если потребуется несколько узлов или отказоустойчивости.

Пример приложения использует кэш распределенной памяти при запуске приложения в среде разработки в Program.cs:

builder.Services.AddDistributedMemoryCache();

Распределенный кэш SQL Server

Реализация распределенного кэша SQL Server (AddDistributedSqlServerCache) позволяет распределенного кэша использовать базу данных SQL Server в качестве резервного хранилища. Чтобы создать таблицу кэшированных элементов SQL Server в экземпляре SQL Server, можно использовать sql-cache средство. Средство создает таблицу с указанным именем и схемой.

Создайте таблицу в SQL Server, выполнив sql-cache create команду. Укажите экземпляр SQL Server (), базу данных (Data Source), схему (Initial Catalogнапример, dbo) и имя таблицы (например, TestCache):

dotnet sql-cache create "Data Source=(localdb)/MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache

В журнал записывается сообщение, указывающее, что средство выполнено успешно:

Table and index were created successfully.

Таблица, sql-cache созданная средством, имеет следующую схему:

Таблица кэша SqlServer

Примечание.

Приложение должно управлять значениями кэша с помощью экземпляра IDistributedCache, а не SqlServerCache.

Пример приложения реализуется в среде, отличной от разработки SqlServerCache , в Program.cs:

builder.Services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = builder.Configuration.GetConnectionString(
        "DistCache_ConnectionString");
    options.SchemaName = "dbo";
    options.TableName = "TestCache";
});

Примечание.

A ConnectionStringTableNameнеобязательно) SchemaName обычно хранятся вне системы управления версиями (например, хранятся в диспетчере секретов или в appsettings.json/appsettings.{Environment}.json файлах). Строка подключения может содержать учетные данные, которые должны храниться вне систем управления версиями.

Распределенный кэш NCache

NCache — это открытый код распределенный кэш в памяти, разработанный изначально в .NET и .NET Core. NCache работает как локально, так и настроен как кластер распределенного кэша для приложения ASP.NET Core, работающего в Azure или на других платформах размещения.

Сведения об установке и настройке NCache на локальном компьютере см. в руководстве по началу работы с Windows (.NET и .NET Core).

Чтобы настроить NCache, выполните приведенные действия.

  1. Установите NCache открытый код NuGet.
  2. Настройте кластер кэша в client.ncconf.
  3. Добавьте следующий код в Program.cs:
builder.Services.AddNCacheDistributedCache(configuration =>
{
    configuration.CacheName = "democache";
    configuration.EnableLogs = true;
    configuration.ExceptionsEnabled = true;
});

Использование распределенного кэша

Чтобы использовать IDistributedCache интерфейс, запросите экземпляр IDistributedCache приложения. Экземпляр предоставляется внедрением зависимостей (DI).

При запуске IDistributedCache примера приложения вставляется в Program.cs. Текущее время кэшируется с помощью IHostApplicationLifetime (дополнительные сведения см. в разделе Generic Host: IHostApplicationLifetime):

app.Lifetime.ApplicationStarted.Register(() =>
{
    var currentTimeUTC = DateTime.UtcNow.ToString();
    byte[] encodedCurrentTimeUTC = System.Text.Encoding.UTF8.GetBytes(currentTimeUTC);
    var options = new DistributedCacheEntryOptions()
        .SetSlidingExpiration(TimeSpan.FromSeconds(20));
    app.Services.GetService<IDistributedCache>()
                              .Set("cachedTimeUTC", encodedCurrentTimeUTC, options);
});

Пример приложения внедряется IDistributedCache на IndexModel страницу индекса.

Каждый раз при загрузке страницы индекса кэш проверяется на время кэширования.OnGetAsync Если кэшированное время не истекло, отображается время. Если 20 секунд истекло с момента последнего доступа к кэшированному времени (время последней загрузки этой страницы), на странице отображается срок действия кэшированного времени.

Немедленно обновите кэшированное время до текущего времени, нажав кнопку "Сброс кэшированного времени ". Кнопка активирует метод обработчика OnPostResetCachedTime .

public class IndexModel : PageModel
{
    private readonly IDistributedCache _cache;

    public IndexModel(IDistributedCache cache)
    {
        _cache = cache;
    }

    public string? CachedTimeUTC { get; set; }
    public string? ASP_Environment { get; set; }

    public async Task OnGetAsync()
    {
        CachedTimeUTC = "Cached Time Expired";
        var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");

        if (encodedCachedTimeUTC != null)
        {
            CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
        }

        ASP_Environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        if (String.IsNullOrEmpty(ASP_Environment))
        {
            ASP_Environment = "Null, so Production";
        }
    }

    public async Task<IActionResult> OnPostResetCachedTime()
    {
        var currentTimeUTC = DateTime.UtcNow.ToString();
        byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
        var options = new DistributedCacheEntryOptions()
            .SetSlidingExpiration(TimeSpan.FromSeconds(20));
        await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);

        return RedirectToPage();
    }
}

Нет необходимости использовать одноэлементное или ограниченное время существования для IDistributedCache экземпляров со встроенными реализациями.

Вы также можете создать IDistributedCache экземпляр, где бы вам ни понадобилось, а не использовать di, но создание экземпляра в коде может сделать код сложнее тестировать и нарушать принцип явных зависимостей.

Рекомендации

При принятии решения о том, какая реализация IDistributedCache лучше всего подходит для вашего приложения, рассмотрите следующее:

  • Существующая инфраструктура
  • Требования к производительности
  • Себестоимость
  • Взаимодействие с командой

Решения кэширования обычно полагаются на хранилище в памяти для быстрого извлечения кэшированных данных, но память является ограниченным ресурсом и дорогостоящим для расширения. В кэше хранятся только часто используемые данные.

Для большинства приложений кэш Redis обеспечивает более высокую пропускную способность и низкую задержку, чем кэш SQL Server. Однако для определения характеристик производительности стратегий кэширования рекомендуется использовать тестовые показатели.

Если SQL Server используется в качестве хранилища резервной копии распределенного кэша, использование одной базы данных для кэша и обычного хранилища данных приложения и извлечения может негативно повлиять на производительность обоих. Рекомендуется использовать выделенный экземпляр SQL Server для хранилища серверной части распределенного кэша.

Дополнительные ресурсы

Распределенный кэш — это кэш, совместно используемый несколькими серверами приложений, как правило, в качестве внешней службы для серверов приложений, к которым он обращается. Распределенный кэш может повысить производительность и масштабируемость приложения ASP.NET Core, особенно если приложение размещается облачной службой или фермой серверов.

Распределенный кэш имеет несколько преимуществ по сравнению с другими сценариями кэширования, в которых кэшированные данные хранятся на отдельных серверах приложений.

При распределении кэшированных данных данные:

  • Последовательный (согласованный) между запросами на несколько серверов.
  • Выживает перезапуски сервера и развертывания приложений.
  • Не использует локальную память.

Конфигурация распределенного кэша является конкретной реализацией. В этой статье описывается настройка распределенных кэшей SQL Server и Redis. Кроме того, доступны сторонние реализации, такие как NCache (NCache на GitHub). Независимо от выбранной реализации приложение взаимодействует с кэшем с помощью IDistributedCache интерфейса.

Просмотреть или скачать образец кода (описание загрузки)

Необходимые компоненты

Чтобы использовать распределенный кэш SQL Server, добавьте ссылку на пакет Microsoft.Extensions.Caching.SqlServer .

Чтобы использовать распределенный кэш Redis, добавьте ссылку на пакет Microsoft.Extensions.Caching.StackExchangeRedis .

Чтобы использовать распределенный кэш NCache, добавьте ссылку на пакет NCache.Microsoft.Extensions.Caching.OpenSource .

Интерфейс IDistributedCache

Интерфейс IDistributedCache предоставляет следующие методы для управления элементами в реализации распределенного кэша:

  • Get: GetAsyncпринимает строковый ключ и извлекает кэшированный элемент в виде byte[] массива, если он найден в кэше.
  • Set, SetAsync: добавляет элемент (в виде byte[] массива) в кэш с помощью строкового ключа.
  • Refresh, RefreshAsync: обновляет элемент в кэше на основе ключа, сбросив время ожидания скольжения срока действия (если таковой имеется).
  • Remove, RemoveAsync: удаляет элемент кэша на основе его строкового ключа.

Установка распределенных служб кэширования

Регистрация реализации IDistributedCache в Startup.ConfigureServices. Предоставляемые платформой реализации, описанные в этом разделе, включают:

Кэш распределенной памяти

Кэш распределенной памяти (AddDistributedMemoryCache) — это платформа, предоставляемая платформой, в IDistributedCache которой хранятся элементы в памяти. Кэш распределенной памяти не является фактическим распределенным кэшем. Кэшированные элементы хранятся экземпляром приложения на сервере, на котором выполняется приложение.

Кэш распределенной памяти — это полезная реализация:

  • В сценариях разработки и тестирования.
  • Если один сервер используется в рабочей среде, а потребление памяти не является проблемой. Реализация распределенного кэша памяти абстрагирует кэшированное хранилище данных. Он позволяет реализовать истинное распределенное решение кэширования в будущем, если потребуется несколько узлов или отказоустойчивости.

Пример приложения использует кэш распределенной памяти при запуске приложения в среде разработки в Startup.ConfigureServices:

services.AddDistributedMemoryCache();

Распределенный кэш SQL Server

Реализация распределенного кэша SQL Server (AddDistributedSqlServerCache) позволяет распределенного кэша использовать базу данных SQL Server в качестве резервного хранилища. Чтобы создать таблицу кэшированных элементов SQL Server в экземпляре SQL Server, можно использовать sql-cache средство. Средство создает таблицу с указанным именем и схемой.

Создайте таблицу в SQL Server, выполнив sql-cache create команду. Укажите экземпляр SQL Server (), базу данных (Data Source), схему (Initial Catalogнапример, dbo) и имя таблицы (например, TestCache):

dotnet sql-cache create "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache

В журнал записывается сообщение, указывающее, что средство выполнено успешно:

Table and index were created successfully.

Таблица, sql-cache созданная средством, имеет следующую схему:

Таблица кэша SqlServer

Примечание.

Приложение должно управлять значениями кэша с помощью экземпляра IDistributedCache, а не SqlServerCache.

Пример приложения реализуется в среде, отличной от разработки SqlServerCache , в Startup.ConfigureServices:

services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = 
        _config["DistCache_ConnectionString"];
    options.SchemaName = "dbo";
    options.TableName = "TestCache";
});

Примечание.

A ConnectionStringTableNameнеобязательно) SchemaName обычно хранятся вне системы управления версиями (например, хранятся в диспетчере секретов или в appsettings.json/appsettings.{Environment}.json файлах). Строка подключения может содержать учетные данные, которые должны храниться вне систем управления версиями.

Распределенный кэш Redis

Redis -это хранилище данных в памяти с открытым исходным кодом, которое часто используется в качестве распределенного кэша. Вы можете настроить кэш Redis Azure для размещенного в Azure приложения ASP.NET Core и использовать кэш Redis Azure для локальной разработки.

Приложение настраивает реализацию кэша с помощью экземпляра RedisCache (AddStackExchangeRedisCache).

  1. Создайте Кэш Azure для Redis.
  2. Скопируйте основной строка подключения (StackExchange.Redis) в конфигурацию.
    • Локальная разработка. Сохранение строка подключения с помощью диспетчера секретов.
    • Azure: сохранение строка подключения в безопасном хранилище, например Azure Key Vault

Следующий код включает Кэш Azure для Redis:

public void ConfigureServices(IServiceCollection services)
{
    if (_hostContext.IsDevelopment())
    {
        services.AddDistributedMemoryCache();
    }
    else
    {
        services.AddStackExchangeRedisCache(options =>
        {
            options.Configuration = _config["MyRedisConStr"];
            options.InstanceName = "SampleInstance";
        });
    }

    services.AddRazorPages();
}

Предыдущий код предполагает, что основной строка подключения (StackExchange.Redis) был сохранен в конфигурации с именем MyRedisConStrключа.

См. сведения на странице с ценами на Azure Cache for Redis.

См . эту проблему GitHub для обсуждения альтернативных подходов к локальному кэшу Redis.

Распределенный кэш NCache

NCache — это открытый код распределенный кэш в памяти, разработанный изначально в .NET и .NET Core. NCache работает как локально, так и настроен как кластер распределенного кэша для приложения ASP.NET Core, работающего в Azure или на других платформах размещения.

Сведения об установке и настройке NCache на локальном компьютере см. в руководстве по началу работы с Windows (.NET и .NET Core).

Чтобы настроить NCache, выполните приведенные действия.

  1. Установите NCache открытый код NuGet.

  2. Настройте кластер кэша в client.ncconf.

  3. Добавьте следующий код в Startup.ConfigureServices:

    services.AddNCacheDistributedCache(configuration =>    
    {        
        configuration.CacheName = "demoClusteredCache";
        configuration.EnableLogs = true;
        configuration.ExceptionsEnabled = true;
    });
    

Использование распределенного кэша

Чтобы использовать IDistributedCache интерфейс, отправьте запрос экземпляра IDistributedCache из любого конструктора в приложении. Экземпляр предоставляется внедрением зависимостей (DI).

При запуске IDistributedCache примера приложения вставляется в Startup.Configure. Текущее время кэшируется с помощью IHostApplicationLifetime (дополнительные сведения см. в разделе Generic Host: IHostApplicationLifetime):

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, 
    IHostApplicationLifetime lifetime, IDistributedCache cache)
{
    lifetime.ApplicationStarted.Register(() =>
    {
        var currentTimeUTC = DateTime.UtcNow.ToString();
        byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
        var options = new DistributedCacheEntryOptions()
            .SetSlidingExpiration(TimeSpan.FromSeconds(20));
        cache.Set("cachedTimeUTC", encodedCurrentTimeUTC, options);
    });

Пример приложения внедряется IDistributedCache на IndexModel страницу индекса.

Каждый раз при загрузке страницы индекса кэш проверяется на время кэширования.OnGetAsync Если кэшированное время не истекло, отображается время. Если 20 секунд истекло с момента последнего доступа к кэшированному времени (время последней загрузки этой страницы), на странице отображается срок действия кэшированного времени.

Немедленно обновите кэшированное время до текущего времени, нажав кнопку "Сброс кэшированного времени ". Кнопка активирует метод обработчика OnPostResetCachedTime .

public class IndexModel : PageModel
{
    private readonly IDistributedCache _cache;

    public IndexModel(IDistributedCache cache)
    {
        _cache = cache;
    }

    public string CachedTimeUTC { get; set; }

    public async Task OnGetAsync()
    {
        CachedTimeUTC = "Cached Time Expired";
        var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");

        if (encodedCachedTimeUTC != null)
        {
            CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
        }
    }

    public async Task<IActionResult> OnPostResetCachedTime()
    {
        var currentTimeUTC = DateTime.UtcNow.ToString();
        byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
        var options = new DistributedCacheEntryOptions()
            .SetSlidingExpiration(TimeSpan.FromSeconds(20));
        await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);

        return RedirectToPage();
    }
}

Примечание.

Время жизни экземпляров IDistributedCache (по крайней мере, для встроенных реализаций) не обязательно должно быть ограничено одним объектом или блоком.

Вы также можете создать IDistributedCache экземпляр, где бы вам ни понадобилось, а не использовать di, но создание экземпляра в коде может сделать код сложнее тестировать и нарушать принцип явных зависимостей.

Рекомендации

При принятии решения о том, какая реализация IDistributedCache лучше всего подходит для вашего приложения, рассмотрите следующее:

  • Существующая инфраструктура
  • Требования к производительности
  • Себестоимость
  • Взаимодействие с командой

Решения кэширования обычно полагаются на хранилище в памяти для быстрого извлечения кэшированных данных, но память является ограниченным ресурсом и дорогостоящим для расширения. В кэше хранятся только часто используемые данные.

Как правило, кэш Redis обеспечивает более высокую пропускную способность и меньшую задержку, чем кэш SQL Server. Однако для определения характеристик производительности стратегий кэширования обычно требуется тестирование.

Если SQL Server используется в качестве хранилища резервной копии распределенного кэша, использование одной базы данных для кэша и обычного хранилища данных приложения и извлечения может негативно повлиять на производительность обоих. Рекомендуется использовать выделенный экземпляр SQL Server для хранилища серверной части распределенного кэша.

Дополнительные ресурсы