Monolitik Persistensi antipattern
Menempatkan semua data aplikasi ke dalam satu penyimpanan data dapat merusak performa, baik karena mengarah pada pertentangan sumber daya, atau karena penyimpanan data tidak cocok untuk beberapa data.
Deskripsi masalah
Secara historis, aplikasi sering menggunakan satu penyimpanan data, terlepas dari berbagai jenis data yang mungkin perlu disimpan oleh aplikasi. Biasanya hal ini dilakukan untuk menyederhanakan desain aplikasi, atau yang lain agar sesuai dengan keahlian tim pengembangan yang ada.
Sistem berbasis cloud modern sering memiliki persyaratan fungsional dan non-fungsional tambahan, dan perlu menyimpan banyak jenis data heterogen, seperti dokumen, gambar, data cache, pesan antrean, log aplikasi, dan telemetri. Mengikuti pendekatan tradisional dan memasukkan semua informasi ini ke dalam penyimpanan data yang sama dapat merusak performa, karena dua alasan utama:
- Menyimpan dan mengambil sejumlah besar data yang tidak terkait di penyimpanan data yang sama dapat menyebabkan ketidakcocokan, yang pada gilirannya menyebabkan waktu respons yang lambat dan kegagalan koneksi.
- Penyimpanan data mana pun yang dipilih, itu mungkin tidak paling cocok untuk semua jenis data yang berbeda, atau mungkin tidak dioptimalkan untuk operasi yang dilakukan aplikasi.
Contoh berikut menunjukkan pengontrol API Web ASP.NET yang menambahkan rekaman baru ke database dan juga merekam hasilnya ke log. Log disimpan dalam database yang sama dengan data bisnis. Anda dapat menemukan sampel lengkap di sini.
public class MonoController : ApiController
{
private static readonly string ProductionDb = ...;
public async Task<IHttpActionResult> PostAsync([FromBody]string value)
{
await DataAccess.InsertPurchaseOrderHeaderAsync(ProductionDb);
await DataAccess.LogAsync(ProductionDb, LogTableName);
return Ok();
}
}
Tingkat di mana rekaman log dihasilkan mungkin akan mempengaruhi performa operasi bisnis. Dan jika komponen lain, seperti monitor proses aplikasi, secara teratur membaca dan memproses data log, itu juga dapat mempengaruhi operasi bisnis.
Cara memperbaiki masalah ini
Memisahkan data sesuai dengan penggunaannya. Untuk setiap himpunan data, pilih penyimpanan data yang paling cocok dengan cara himpunan data tersebut akan digunakan. Dalam contoh sebelumnya, aplikasi harus masuk ke toko terpisah dari database yang menyimpan data bisnis:
public class PolyController : ApiController
{
private static readonly string ProductionDb = ...;
private static readonly string LogDb = ...;
public async Task<IHttpActionResult> PostAsync([FromBody]string value)
{
await DataAccess.InsertPurchaseOrderHeaderAsync(ProductionDb);
// Log to a different data store.
await DataAccess.LogAsync(LogDb, LogTableName);
return Ok();
}
}
Pertimbangan
Pisahkan data dengan cara digunakan dan bagaimana aksesnya. Misalnya, jangan menyimpan informasi log dan data bisnis di penyimpanan data yang sama. Jenis data ini memiliki persyaratan dan pola akses yang berbeda secara signifikan. Rekaman log secara inheren berurutan, sementara data bisnis lebih cenderung memerlukan akses acak, dan seringkali relasional.
Pertimbangkan pola akses data untuk setiap jenis data. Misalnya, simpan laporan dan dokumen berformat dalam database dokumen seperti Azure Cosmos DB, tetapi gunakan Azure Cache for Redis untuk menyimpan data sementara.
Jika Anda mengikuti panduan ini tetapi masih mencapai batas database, Anda mungkin perlu meningkatkan database. Juga pertimbangkan untuk menskalakan secara horizontal dan pemartisian beban di seluruh server database. Namun, pemartisian mungkin memerlukan mendesain ulang aplikasi. Untuk informasi selengkapnya, lihat Pemartisian data.
Cara mendeteksi masalah
Sistem kemungkinan akan melambat secara dramatis dan akhirnya gagal, karena sistem kehabisan sumber daya seperti koneksi database.
Anda dapat melakukan langkah-langkah berikut untuk membantu mengidentifikasi masalah ini.
- Instrumen sistem untuk merekam statistik performa utama. Ambil informasi waktu untuk setiap operasi, serta poin-poin di mana aplikasi membaca dan menulis data.
- Jika memungkinkan, pantau sistem yang berjalan selama beberapa hari di lingkungan produksi untuk mendapatkan pandangan dunia nyata tentang bagaimana sistem digunakan. Jika hal ini tidak mungkin, jalankan tes beban skrip dengan volume realistis pengguna virtual yang melakukan serangkaian operasi yang khas.
- Gunakan data telemetri untuk mengidentifikasi periode performa yang buruk.
- Identifikasi penyimpanan data mana yang diakses selama periode tersebut.
- Identifikasi sumber daya penyimpanan data yang mungkin mengalami ketidakcocokan.
Contoh diagnosis
Bagian berikut menerapkan langkah-langkah ini ke aplikasi contoh yang dijelaskan sebelumnya.
Instrumen dan memantau sistem
Grafik berikut menunjukkan hasil pengujian beban aplikasi contoh yang dijelaskan sebelumnya. Tes ini menggunakan beban langkah hingga 1000 pengguna bersamaan.
Ketika beban meningkat menjadi 700 pengguna, begitu juga throughput. Tetapi pada titik itu, tingkat throughput mati, dan sistem tampaknya berjalan pada kapasitas maksimumnya. Respons rata-rata secara bertahap meningkat dengan beban pengguna, menunjukkan bahwa sistem tidak dapat mengikuti permintaan.
Mengidentifikasi periode performa yang buruk
Jika Anda memantau sistem produksi, Anda mungkin melihat pola. Misalnya, waktu respons mungkin turun secara signifikan pada waktu yang sama setiap hari. Hal ini bisa disebabkan oleh beban kerja reguler atau tugas batch terjadwal, atau hanya karena sistem memiliki lebih banyak pengguna pada waktu-waktu tertentu. Anda harus fokus pada data telemetri untuk peristiwa ini.
Carilah korelasi antara waktu respons yang meningkat dan peningkatan aktivitas database atau I/O ke sumber daya bersama. Jika ada korelasi, itu berarti database mungkin menjadi penyempitan.
Identifikasi penyimpanan data mana yang diakses selama periode tersebut
Grafik berikutnya menunjukkan pemanfaatan unit throughput database (DTU) selama pengujian beban. (DTU adalah ukuran kapasitas yang tersedia, dan merupakan kombinasi pemanfaatan CPU, alokasi memori, laju I/O.) Pemanfaatan DTU dengan cepat mencapai 100%. Hal ini kira-kira merupakan titik di mana throughput memuncak pada grafik sebelumnya. Pemanfaatan database tetap sangat tinggi sampai tes selesai. Ada sedikit penurunan menjelang akhir, yang bisa disebabkan oleh pembatasan, persaingan untuk koneksi database, atau faktor lainnya.
Periksa telemetri untuk penyimpanan data
Instrumen penyimpanan data untuk menangkap detail tingkat rendah dari aktivitas. Dalam aplikasi contoh, statistik akses data menunjukkan volume operasi penyisipan yang tinggi dilakukan PurchaseOrderHeader
terhadap tabel dan MonoLog
tabel.
Mengidentifikasi ketidakcocokan sumber daya
Pada titik ini, Anda dapat meninjau kode sumber, dengan fokus pada titik-titik di mana sumber daya yang bersaing diakses oleh aplikasi. Carilah situasi seperti:
- Data yang secara logis terpisah ditulis ke toko yang sama. Data seperti log, laporan, dan pesan yang mengantre tidak boleh disimpan dalam database yang sama dengan informasi bisnis.
- Ketidakcocokan antara pilihan penyimpanan data dan jenis data, seperti blob atau dokumen XML dalam database relasional.
- Data dengan pola penggunaan yang berbeda secara signifikan yang berbagi toko yang sama, seperti data tulis tinggi / membaca rendah yang disimpan dengan data tulis rendah / membaca tinggi.
Menerapkan solusi dan memverifikasi hasilnya
Aplikasi diubah untuk menulis log ke penyimpanan data terpisah. Berikut adalah hasil uji beban:
Pola throughput mirip dengan grafik sebelumnya, tetapi titik di mana puncak performa sekitar 500 permintaan per detik lebih tinggi. Waktu respons rata-rata sedikit lebih rendah. Namun, statistik ini tidak menceritakan kisah lengkapnya. Telemetri untuk database bisnis ini menunjukkan bahwa tingkat pemanfaatan DTU mencapai sekitar 75%, bukan 100%.
Demikian pula, pemanfaatan DTU maksimum dari database log hanya mencapai sekitar 70%. Database tidak lagi menjadi faktor pembatas dalam performa sistem.