Bagikan melalui


Pustaka HybridCache di ASP.NET Core

Penting

HybridCache saat ini masih dalam pratinjau tetapi akan sepenuhnya dirilis setelah .NET 9.0 dalam rilis minor ekstensi .NET di masa mendatang.

Artikel ini menjelaskan cara mengonfigurasi dan menggunakan HybridCache pustaka di aplikasi ASP.NET Core. Untuk pengenalan pustaka, lihat bagian HybridCache ringkasan Penembolokan.

Dapatkan pustaka

Pasang paket Microsoft.Extensions.Caching.Hybrid.

dotnet add package Microsoft.Extensions.Caching.Hybrid --version "9.0.0-preview.7.24406.2"

Mendaftarkan layanan

HybridCache Tambahkan layanan ke kontainer injeksi dependensi (DI) dengan memanggil AddHybridCache:

// Add services to the container.
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddAuthorization();

builder.Services.AddHybridCache();

Kode sebelumnya mendaftarkan HybridCache layanan dengan opsi default. API pendaftaran juga dapat mengonfigurasi opsi dan serialisasi.

Mendapatkan dan menyimpan entri cache

Layanan ini HybridCache menyediakan GetOrCreateAsync metode dengan dua kelebihan beban, mengambil kunci dan:

  • Metode pabrik.
  • Status, dan metode pabrik.

Metode ini menggunakan kunci untuk mencoba mengambil objek dari cache utama. Jika item tidak ditemukan di cache utama (cache meleset), item kemudian memeriksa cache sekunder jika dikonfigurasi. Jika tidak menemukan data di sana (cache miss lain), ia memanggil metode pabrik untuk mendapatkan objek dari sumber data. Kemudian menyimpan objek di cache primer dan sekunder. Metode pabrik tidak pernah dipanggil jika objek ditemukan di cache primer atau sekunder (hit cache).

Layanan HybridCache ini memastikan bahwa hanya satu penelepon bersamaan untuk kunci tertentu yang memanggil metode pabrik, dan semua penelepon lainnya menunggu hasil panggilan tersebut. Yang CancellationToken diteruskan untuk GetOrCreateAsync mewakili pembatalan gabungan semua pemanggil bersamaan.

Kelebihan beban utama GetOrCreateAsync

Kelebihan beban GetOrCreateAsync stateless direkomendasikan untuk sebagian besar skenario. Kode untuk menyebutnya relatif sederhana. Berikut contohnya:

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;
    }
}

Kelebihan beban alternatif GetOrCreateAsync

Kelebihan beban alternatif dapat mengurangi beberapa overhead dari variabel yang ditangkap dan panggilan balik per instans, tetapi dengan mengorbankan kode yang lebih kompleks. Untuk sebagian besar skenario peningkatan performa tidak melebihi kompleksitas kode. Berikut adalah contoh yang menggunakan kelebihan beban alternatif:

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;
    }
}

Metode SetAsync

Dalam banyak skenario, GetOrCreateAsync adalah satu-satunya API yang diperlukan. Tetapi HybridCache juga harus SetAsync menyimpan objek di cache tanpa mencoba mengambilnya terlebih dahulu.

Hapus entri cache menurut kunci

Ketika data yang mendasar untuk entri cache berubah sebelum kedaluwarsa, hapus entri secara eksplisit dengan memanggil RemoveAsync dengan kunci ke entri. Kelebihan beban memungkinkan Anda menentukan kumpulan nilai kunci.

Ketika entri dihapus, entri dihapus dari cache primer dan sekunder.

Menghapus entri cache menurut tag

Tag dapat digunakan untuk mengelompokkan entri cache dan membatalkannya bersama-sama.

Atur tag saat memanggil GetOrCreateAsync, seperti yang ditunjukkan dalam contoh berikut:

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;
    }
}

Hapus semua entri untuk tag tertentu dengan memanggil RemoveByTagAsync dengan nilai tag. Kelebihan beban memungkinkan Anda menentukan kumpulan nilai tag.

Ketika entri dihapus, entri dihapus dari cache primer dan sekunder.

Opsi

Metode AddHybridCache ini dapat digunakan untuk mengonfigurasi default global. Contoh berikut menunjukkan cara mengonfigurasi beberapa opsi yang tersedia:

// 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)
        };
    });

Metode ini GetOrCreateAsync juga dapat mengambil HybridCacheEntryOptions objek untuk mengambil alih default global untuk entri cache tertentu. Berikut contohnya:

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;
    }
}

Untuk informasi selengkapnya tentang opsi, lihat kode sumber:

Batas

Properti HybridCacheOptions berikut memungkinkan Anda mengonfigurasi batasan yang berlaku untuk semua entri cache:

  • MaximumPayloadBytes - Ukuran maksimum entri cache. Nilai defaultnya adalah 1 MB. Upaya untuk menyimpan nilai dalam ukuran ini dicatat, dan nilainya tidak disimpan dalam cache.
  • MaximumKeyLength - Panjang maksimum kunci cache. Nilai defaultnya adalah 1024 karakter. Upaya untuk menyimpan nilai dalam ukuran ini dicatat, dan nilainya tidak disimpan dalam cache.

Serialisasi

Penggunaan cache sekunder dan di luar proses memerlukan serialisasi. Serialisasi dikonfigurasi sebagai bagian dari mendaftarkan HybridCache layanan. Serializer khusus jenis dan tujuan umum dapat dikonfigurasi melalui AddSerializer metode dan AddSerializerFactory , ditautkan dari AddHybridCache panggilan. Secara default, pustaka menangani string dan byte[] secara internal, dan menggunakan System.Text.Json untuk yang lain. HybridCache juga dapat menggunakan serializer lain, seperti protobuf atau XML.

Contoh berikut mengonfigurasi layanan untuk menggunakan serializer protobuf khusus jenis:

// 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>>();

Contoh berikut mengonfigurasi layanan untuk menggunakan serializer protobuf tujuan umum yang dapat menangani banyak jenis 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>();

Cache sekunder memerlukan penyimpanan data, seperti Redis atau SqlServer. Untuk menggunakan Azure Cache for Redis, misalnya:

  • Pasang paket Microsoft.Extensions.Caching.StackExchangeRedis.

  • Buat instans Azure Cache for Redis.

  • Dapatkan string koneksi yang tersambung ke instans Redis. Temukan string koneksi dengan memilih Tampilkan kunci akses di halaman Gambaran Umum di portal Azure.

  • Simpan string koneksi dalam konfigurasi aplikasi. Misalnya, gunakan file rahasia pengguna yang terlihat seperti JSON berikut, dengan string koneksi di bagian .ConnectionStrings Ganti <the connection string> dengan string koneksi aktual:

    {
      "ConnectionStrings": {
        "RedisConnectionString": "<the connection string>"
      }
    }
    
  • Daftar di DI IDistributedCache implementasi yang disediakan paket Redis. Untuk melakukan itu, panggil AddStackExchangeRedisCache, dan teruskan string koneksi. Contohnya:

    builder.Services.AddStackExchangeRedisCache(options =>
    {
        options.Configuration = 
            builder.Configuration.GetConnectionString("RedisConnectionString");
    });
    
  • Implementasi Redis IDistributedCache sekarang tersedia dari kontainer DI aplikasi. HybridCache menggunakannya sebagai cache sekunder dan menggunakan serializer yang dikonfigurasi untuk cache tersebut.

Untuk informasi selengkapnya, lihat aplikasi sampel serialisasi HybridCache.

Penyimpanan cache

Secara default HybridCache menggunakan MemoryCache untuk penyimpanan cache utamanya. Entri cache disimpan dalam proses, sehingga setiap server memiliki cache terpisah yang hilang setiap kali proses server dimulai ulang. Untuk penyimpanan di luar proses sekunder, seperti Redis atau SQL Server, HybridCache menggunakan implementasi yang dikonfigurasi IDistributedCache , jika ada. Tetapi bahkan tanpa IDistributedCacheimplementasi, HybridCache layanan masih memberikan perlindungan penembolokan dan stempel dalam proses.

Mengoptimalkan performa

Untuk mengoptimalkan performa, konfigurasikan HybridCache untuk menggunakan kembali objek dan menghindari byte[] alokasi.

Gunakan kembali objek

Dengan menggunakan kembali instans, HybridCache dapat mengurangi overhead CPU dan alokasi objek yang terkait dengan deserialisasi per panggilan. Hal ini dapat menyebabkan peningkatan performa dalam skenario di mana objek yang di-cache besar atau sering diakses.

Dalam kode umum yang ada yang menggunakan IDistributedCache, setiap pengambilan objek dari cache menghasilkan deserialisasi. Perilaku ini berarti bahwa setiap pemanggil bersamaan mendapatkan instans terpisah dari objek, yang tidak dapat berinteraksi dengan instans lain. Hasilnya adalah keamanan utas, karena tidak ada risiko modifikasi bersamaan pada instans objek yang sama.

Karena banyak HybridCache penggunaan akan diadaptasi dari kode yang ada IDistributedCache , HybridCache mempertahankan perilaku ini secara default untuk menghindari memperkenalkan bug konkurensi. Namun, objek secara inheren aman utas jika:

  • Mereka adalah jenis yang tidak dapat diubah.
  • Kode tidak mengubahnya.

Dalam kasus seperti itu, informasikan HybridCache bahwa aman untuk menggunakan kembali instans dengan:

  • Menandai jenis sebagai sealed. Kata sealed kunci dalam C# berarti bahwa kelas tidak dapat diwariskan.
  • Menerapkan atribut ke [ImmutableObject(true)] jenis . Atribut [ImmutableObject(true)] menunjukkan bahwa status objek tidak dapat diubah setelah dibuat.

Hindari byte[] alokasi

HybridCache juga menyediakan API opsional untuk IDistributedCache implementasi, untuk menghindari byte[] alokasi. Fitur ini diimplementasikan oleh versi pratinjau paket Microsoft.Extensions.Caching.StackExchangeRedis dan Microsoft.Extensions.Caching.SqlServer . Untuk informasi selengkapnya, lihat IBufferDistributedCache Berikut adalah perintah .NET CLI untuk menginstal paket:

dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis --prerelease
dotnet add package Microsoft.Extensions.Caching.SqlServer --prerelease

Implementasi HybridCache Kustom

Implementasi konkret dari HybridCache kelas abstrak disertakan dalam kerangka kerja bersama dan disediakan melalui injeksi dependensi. Tetapi pengembang dipersilakan untuk memberikan implementasi kustom API.

Kompatibilitas

Pustaka HybridCache mendukung runtime .NET yang lebih lama, hingga .NET Framework 4.7.2 dan .NET Standard 2.0.

Sumber Daya Tambahan:

Untuk informasi selengkapnya tentang HybridCache, lihat sumber daya berikut ini: