Pola Cache-Aside

Azure Cache for Redis

Memuat data sesuai permintaan ke dalam cache dari penyimpanan data. Hal ini dapat meningkatkan performa dan juga membantu menjaga konsistensi antara data yang disimpan di tembolokan dan data yang ada di penyimpanan data utama.

Konteks dan masalah

Aplikasi menggunakan cache untuk meningkatkan akses berulang ke informasi yang disimpan di penyimpanan data. Namun, tidak praktis untuk mengharapkan bahwa data yang di-cache akan selalu benar-benar konsisten dengan data di penyimpanan data. Aplikasi harus menerapkan strategi yang membantu memastikan bahwa data dalam cache selalu mutakhir, tetapi juga dapat mendeteksi dan menangani situasi yang muncul saat data dalam cache menjadi basi.

Solusi

Banyak sistem penembolokan komersial menyediakan operasi baca-tayang dan tulis-tayang/tulis-di belakang. Dalam sistem ini, aplikasi mengambil data dengan mereferensikan cache. Jika data tidak ada dalam cache, data diambil dari penyimpanan data dan ditambahkan ke cache. Setiap modifikasi pada data yang disimpan dalam cache juga secara otomatis ditulis kembali ke penyimpanan data.

Untuk cache yang tidak menyediakan fungsionalitas ini, merupakan tanggung jawab aplikasi yang menggunakan cache untuk memelihara data.

Aplikasi dapat meniru fungsionalitas penembolokan baca-tayang dengan menerapkan strategi penyisihan cache. Strategi ini memuat data ke dalam cache sesuai permintaan. Gambar tersebut mengilustrasikan penggunaan pola Cache-Aside untuk menyimpan data dalam cache.

Menggunakan pola Cache-Aside untuk menyimpan data dalam cache

Jika aplikasi memperbarui informasi, itu dapat mengikuti strategi penulisan dengan membuat modifikasi pada penyimpanan data, dan dengan membatalkan item yang sesuai dalam cache.

Saat item berikutnya diperlukan, menggunakan strategi penyisihan cache akan menyebabkan data yang diperbarui diambil dari penyimpanan data dan ditambahkan kembali ke cache.

Masalah dan pertimbangan

Pertimbangkan poin-poin berikut saat memutuskan cara menerapkan pola ini:

Seumur hidup data yang di-cache. Banyak cache menerapkan kebijakan kedaluwarsa yang membuat data tidak valid dan menghapusnya dari cache jika tidak diakses selama jangka waktu tertentu. Agar selain cache efektif, pastikan bahwa kebijakan kedaluwarsa cocok dengan pola akses untuk aplikasi yang menggunakan data. Jangan membuat periode kedaluwarsa terlalu pendek karena ini dapat menyebabkan aplikasi terus-menerus mengambil data dari penyimpanan data dan menambahkannya ke cache. Demikian pula, jangan membuat periode kedaluwarsa terlalu lama sehingga data yang di-cache cenderung menjadi basi. Ingat bahwa penembolokan paling efektif untuk data yang relatif statis, atau data yang sering dibaca.

Data penggusuran. Sebagian besar cache memiliki ukuran terbatas dibandingkan dengan penyimpanan data tempat data berasal, dan mereka akan menghapus data jika diperlukan. Sebagian besar cache mengadopsi kebijakan yang paling jarang digunakan untuk memilih item yang akan dikeluarkan, tetapi ini mungkin dapat disesuaikan. Konfigurasikan properti kedaluwarsa global dan properti lain dari cache, dan properti kedaluwarsa dari setiap item yang di-cache, untuk memastikan bahwa cache hemat biaya. Tidak selalu tepat untuk menerapkan kebijakan pengusiran global ke setiap item dalam cache. Misalnya, jika item yang di-cache sangat mahal untuk diambil dari penyimpanan data, akan bermanfaat untuk menyimpan item ini di cache dengan mengorbankan item yang lebih sering diakses tetapi lebih murah.

Mempersiapkan cache. Banyak solusi yang mengisi cache terlebih dahulu dengan data yang mungkin dibutuhkan aplikasi sebagai bagian dari pemrosesan startup. Pola Cache-Aside masih dapat berguna jika beberapa data ini kedaluwarsa atau dihapus.

Konsistensi. Menerapkan pola Cache-Aside tidak menjamin konsistensi antara penyimpanan data dan cache. Item dalam penyimpanan data dapat diubah kapan saja oleh proses eksternal, dan perubahan ini mungkin tidak tercermin dalam cache hingga item dimuat berikutnya. Dalam sistem yang mereplikasi data di seluruh penyimpanan data, masalah ini dapat menjadi serius jika sinkronisasi sering terjadi.

Penembolokan lokal (dalam memori). Cache dapat berupa lokal ke instans aplikasi dan disimpan dalam memori. Selain cache dapat berguna dalam lingkungan ini jika aplikasi berulang kali mengakses data yang sama. Namun, cache lokal bersifat pribadi dan instans aplikasi yang berbeda masing-masing dapat memiliki salinan data cache yang sama. Data ini dapat dengan cepat menjadi tidak konsisten di antara cache, sehingga data yang disimpan di cache pribadi mungkin perlu kedaluwarsa dan menyegarkannya lebih sering. Dalam skenario ini, pertimbangkan untuk menyelidiki penggunaan mekanisme penembolokan bersama atau terdistribusi.

Kapan menggunakan pola ini

Gunakan pola ini ketika:

  • Cache tidak menyediakan operasi baca-tayang dan tulis-tayang asli.
  • Permintaan sumber daya tidak dapat diprediksi. Pola ini memungkinkan aplikasi memuat data sesuai permintaan. Itu tidak membuat asumsi tentang data mana yang akan dibutuhkan aplikasi sebelumnya.

Pola ini mungkin tidak cocok:

  • Ketika himpunan data yang di-cache statis. Jika data sesuai dengan ruang cache yang tersedia, siapkan cache dengan data saat startup dan terapkan kebijakan yang mencegah data kedaluwarsa.
  • Untuk informasi status sesi penembolokan dalam aplikasi web yang dihosting di pertanian web. Dalam lingkungan ini, Anda harus menghindari memperkenalkan dependensi berdasarkan afinitas klien-server.

Desain beban kerja

Arsitek harus mengevaluasi bagaimana pola Cache-Aside dapat digunakan dalam desain beban kerja mereka untuk mengatasi tujuan dan prinsip yang tercakup dalam pilar Azure Well-Architected Framework. Contohnya:

Pilar Bagaimana pola ini mendukung tujuan pilar
Keputusan desain keandalan membantu beban kerja Anda menjadi tahan terhadap kerusakan dan untuk memastikan bahwa keputusan tersebut pulih ke status berfungsi penuh setelah kegagalan terjadi. Penembolokan membuat replikasi data dan, dengan cara terbatas, dapat digunakan untuk mempertahankan ketersediaan data yang sering diakses jika penyimpanan data asal sementara tidak tersedia. Selain itu, jika ada kerusakan dalam cache, beban kerja dapat kembali ke penyimpanan data asal.

- RE:05 Redundansi
Efisiensi Performa membantu beban kerja Anda memenuhi tuntutan secara efisien melalui pengoptimalan dalam penskalaan, data, kode. Performa yang lebih baik dalam beban kerja Anda dapat diperoleh saat menggunakan cache untuk data baca-berat yang tidak sering berubah dan beban kerja Anda dirancang untuk mentolerir sejumlah keusangan tertentu.

- Performa DATA PE:08
- Pengoptimalan performa berkelanjutan PE:12

Seperti halnya keputusan desain apa pun, pertimbangkan tradeoff terhadap tujuan pilar lain yang mungkin diperkenalkan dengan pola ini.

Contoh

Di Microsoft Azure, Anda dapat menggunakan Azure Cache for Redis untuk membuat cache terdistribusi yang dapat dibagikan oleh beberapa instans aplikasi.

Contoh kode berikut ini menggunakan klien StackExchange.Redis , yang merupakan pustaka klien Redis yang ditulis untuk .NET. Untuk menyambungkan ke instans Azure Cache for Redis, panggil metode ConnectionMultiplexer.Connect statis dan teruskan string koneksi. Metode mengembalikan ConnectionMultiplexer yang mewakili koneksi. Salah satu pendekatan untuk berbagi instans ConnectionMultiplexer dalam aplikasi Anda adalah dengan memiliki properti statis yang mengembalikan instans terhubung, mirip dengan instans berikut. Pendekatan ini menyediakan cara rangkaian-aman untuk menginisialisasi hanya satu instans yang terhubung.

private static ConnectionMultiplexer Connection;

// Redis connection string information
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
    string cacheConnection = ConfigurationManager.AppSettings["CacheConnection"].ToString();
    return ConnectionMultiplexer.Connect(cacheConnection);
});

public static ConnectionMultiplexer Connection => lazyConnection.Value;

Metode GetMyEntityAsync dalam contoh kode berikut menunjukkan implementasi pola Cache-Aside. Metode ini mengambil objek dari cache menggunakan pendekatan baca-tayang.

Sebuah objek diidentifikasi dengan menggunakan ID integer sebagai kunci. Metode GetMyEntityAsync mencoba mengambil item dengan kunci ini dari cache. Jika item yang cocok ditemukan, itu dikembalikan. Jika tidak ada kecocokan dalam cache, metode GetMyEntityAsync mengambil objek dari penyimpanan data, menambahkannya ke cache, lalu mengembalikannya. Kode yang sebenarnya membaca data dari data store tidak ditampilkan di sini, karena tergantung pada data store. Perhatikan bahwa item yang di-cache dikonfigurasi untuk kedaluwarsa untuk mencegahnya menjadi basi jika diperbarui di tempat lain.

// Set five minute expiration as a default
private const double DefaultExpirationTimeInMinutes = 5.0;

public async Task<MyEntity> GetMyEntityAsync(int id)
{
  // Define a unique key for this method and its parameters.
  var key = $"MyEntity:{id}";
  var cache = Connection.GetDatabase();

  // Try to get the entity from the cache.
  var json = await cache.StringGetAsync(key).ConfigureAwait(false);
  var value = string.IsNullOrWhiteSpace(json)
                ? default(MyEntity)
                : JsonConvert.DeserializeObject<MyEntity>(json);

  if (value == null) // Cache miss
  {
    // If there's a cache miss, get the entity from the original store and cache it.
    // Code has been omitted because it is data store dependent.
    value = ...;

    // Avoid caching a null value.
    if (value != null)
    {
      // Put the item in the cache with a custom expiration time that
      // depends on how critical it is to have stale data.
      await cache.StringSetAsync(key, JsonConvert.SerializeObject(value)).ConfigureAwait(false);
      await cache.KeyExpireAsync(key, TimeSpan.FromMinutes(DefaultExpirationTimeInMinutes)).ConfigureAwait(false);
    }
  }

  return value;
}

Contoh menggunakan Azure Cache for Redis untuk mengakses penyimpanan dan mengambil informasi dari cache. Untuk informasi selengkapnya, lihat Menggunakan Azure Cache for Redis dan Cara membuat Aplikasi Web dengan Azure Cache for Redis.

Metode UpdateEntityAsync yang ditampilkan di bawah ini menunjukkan cara membatalkan objek dalam cache saat nilainya diubah oleh aplikasi. Kode memperbarui penyimpanan data asli dan kemudian menghapus item yang di-cache dari cache.

public async Task UpdateEntityAsync(MyEntity entity)
{
    // Update the object in the original data store.
    await this.store.UpdateEntityAsync(entity).ConfigureAwait(false);

    // Invalidate the current cache object.
    var cache = Connection.GetDatabase();
    var id = entity.Id;
    var key = $"MyEntity:{id}"; // The key for the cached object.
    await cache.KeyDeleteAsync(key).ConfigureAwait(false); // Delete this key from the cache.
}

Catatan

Urutan langkah itu penting. Perbarui penyimpanan data sebelum menghapus item dari tembolok. Jika Anda menghapus item yang di-cache terlebih dahulu, ada sedikit waktu ketika klien mungkin mengambil item sebelum penyimpanan data diperbarui. Itu akan mengakibatkan cache hilang (karena item telah dihapus dari cache), menyebabkan versi item sebelumnya diambil dari penyimpanan data dan ditambahkan kembali ke cache. Hasilnya akan menjadi data cache yang basi.

Informasi berikut mungkin relevan saat menerapkan pola ini:

  • Pola aplikasi web yang andal menunjukkan kepada Anda cara menerapkan pola cache-aside ke aplikasi web yang berkonvergsi di cloud.

  • Panduan Penembolokan. Memberikan informasi tambahan tentang bagaimana Anda bisa menyimpan data dalam solusi cloud, dan masalah yang harus Anda pertimbangkan saat menerapkan cache.

  • Data Consistency Primer. Aplikasi cloud biasanya menggunakan data yang tersebar di seluruh penyimpanan data. Mengelola dan menjaga konsistensi data dalam lingkungan ini merupakan aspek penting dari sistem, terutama masalah konkurensi dan ketersediaan yang dapat muncul. Primer ini menjelaskan masalah tentang konsistensi di seluruh data terdistribusi, dan merangkum bagaimana aplikasi dapat menerapkan konsistensi akhirnya untuk menjaga ketersediaan data.