Memahami keandalan

Dokumen ini memberikan pemahaman tentang fitur keandalan BigQuery, seperti ketersediaan, ketahanan, konsistensi data, konsistensi performa, pemulihan data, dan tinjauan pertimbangan penanganan error.

Pendahuluan ini membantu Anda membahas tiga pertimbangan utama:

  • Menentukan apakah BigQuery adalah alat yang tepat untuk tugas Anda.
  • Memahami dimensi keandalan BigQuery.
  • Mengidentifikasi persyaratan keandalan khusus untuk kasus penggunaan tertentu.

Memilih BigQuery

BigQuery adalah Data Warehouse perusahaan yang terkelola sepenuhnya dan dibuat untuk menyimpan dan menganalisis set data besar. Library ini menyediakan cara untuk menyerap, menyimpan, membaca, dan membuat kueri megabyte hingga petabyte data dengan performa yang konsisten tanpa harus mengelola infrastruktur yang mendasarinya. Karena kekuatan dan performanya, BigQuery sangat cocok untuk digunakan di berbagai solusi. Beberapa di antaranya didokumentasikan secara mendetail sebagai pola referensi.

Umumnya, BigQuery sangat cocok untuk workload yang menyerap dan menganalisis data dalam jumlah besar. Secara khusus, platform ini dapat di-deploy secara efektif untuk kasus penggunaan seperti analisis data prediktif dan real-time (dengan penyerapan streaming serta BigQuery ML), deteksi anomali, dan kasus penggunaan lainnya yang penting untuk menganalisis data dalam jumlah besar dengan performa yang dapat diprediksi. Namun, jika Anda mencari database untuk mendukung aplikasi gaya Pemrosesan Transaksi Online (OLTP), sebaiknya pertimbangkan layanan Google Cloud lainnya seperti Spanner, Cloud SQL, atau Bigtable yang mungkin lebih cocok untuk kasus penggunaan ini.

Dimensi keandalan di BigQuery

Ketersediaan

Ketersediaan menentukan kemampuan pengguna untuk membaca data dari BigQuery atau menulis data ke BigQuery. BigQuery dibuat untuk menjadikan keduanya sangat tersedia dengan SLA 99,99%. Ada dua komponen yang terlibat dalam kedua operasi tersebut:

  • Layanan BigQuery
  • Resource komputasi yang diperlukan untuk menjalankan kueri tertentu

Keandalan layanan adalah fungsi dari BigQuery API tertentu yang digunakan untuk mengambil data. Ketersediaan resource komputasi bergantung pada kapasitas yang tersedia bagi pengguna pada saat kueri dijalankan. Lihat bagian Memahami slot untuk mengetahui informasi selengkapnya tentang unit dasar komputasi untuk BigQuery dan ekonomi resource slot yang dihasilkan.

Ketahanan

Ketahanan dibahas dalam bab Mengimplementasikan SLO di Workbook SRE dan dijelaskan sebagai "proporsi data yang dapat berhasil dibaca".

Konsistensi data

Konsistensi menentukan ekspektasi yang dimiliki pengguna terkait bagaimana data dapat dikueri setelah ditulis atau diubah. Salah satu aspek konsistensi data adalah memastikan semantik "tepat satu kali" untuk penyerapan data. Untuk mengetahui informasi selengkapnya, lihat "Keandalan solusi" di Contoh kasus penggunaan dalam memuat data dan Mencoba kembali penyisipan tugas yang gagal.

Konsistensi performa

Secara umum, performa dapat dinyatakan dalam dua dimensi. Latensi adalah ukuran waktu eksekusi operasi pengambilan data yang panjang seperti kueri. Throughput adalah ukuran jumlah data yang dapat diproses BigQuery selama jangka waktu tertentu. Berkat desain multi-tenant BigQuery yang skalabel secara horizontal, throughput-nya dapat ditingkatkan ke berbagai ukuran data. Tingkat kepentingan relatif terhadap latensi dan throughput ditentukan oleh kasus penggunaan tertentu.

Pemulihan data

Dua cara untuk mengukur kemampuan pemulihan data setelah terjadi pemadaman adalah:

  • Batas Waktu Pemulihan (RTO). Berapa lama data tidak tersedia setelah terjadi insiden.
  • Toleransi Jumlah Data yang Hilang (RPO). Berapa banyak data yang dikumpulkan sebelum insiden boleh hilang.

Pertimbangan ini sangat relevan jika zona atau region mengalami pemadaman layanan yang merusak atau merusak selama beberapa hari.

Perencanaan penanganan bencana

Meskipun istilah "bencana" dapat menimbulkan gambaran tentang bencana alam, cakupan bagian ini membahas kegagalan spesifik mulai dari hilangnya satu mesin hingga hilangnya suatu wilayah. Peristiwa pertama adalah kejadian sehari-hari yang ditangani BigQuery secara otomatis, sedangkan peristiwa yang kedua adalah sesuatu yang mungkin harus ditangani oleh pelanggan dalam mendesain arsitektur mereka jika diperlukan. Memahami cakupan perencanaan penanganan bencana yang berhubungan dengan tanggung jawab pelanggan sangatlah penting.

BigQuery menawarkan SLA waktu beroperasi 99,99% yang terdepan di industri. Hal ini dimungkinkan oleh arsitektur regional BigQuery yang menulis data di dua zona berbeda dan menyediakan kapasitas komputasi redundan. Penting untuk diingat bahwa SLA BigQuery sama untuk region, misalnya us-central1, dan multi-region, misalnya AS.

Penanganan skenario otomatis

Karena BigQuery adalah layanan regional, BigQuery bertanggung jawab untuk menangani hilangnya mesin atau bahkan seluruh zona secara otomatis. Fakta bahwa BigQuery dibuat di atas zona dibuat abstrak dari pengguna.

Kehilangan mesin

Kegagalan mesin adalah kejadian sehari-hari dalam skala operasional Google. BigQuery dirancang untuk menangani kegagalan mesin secara otomatis tanpa memengaruhi zona penampung.
Pada dasarnya, eksekusi kueri dibagi menjadi tugas-tugas kecil yang dapat dikirim secara paralel ke banyak mesin. Hilangnya atau penurunan performa mesin secara tiba-tiba ditangani secara otomatis dengan mengirim ulang pekerjaan ke mesin yang berbeda. Pendekatan tersebut penting untuk mengurangi latensi tail.

BigQuery menggunakan encoding Reed–Solomon untuk menyimpan salinan zona data Anda secara efisien dan tahan lama. Dalam peristiwa yang sangat jarang terjadi, yaitu ketika beberapa kegagalan mesin menyebabkan hilangnya salinan zona, data juga disimpan dengan cara yang sama di setidaknya satu zona lainnya. Dalam kasus semacam ini, BigQuery akan mendeteksi masalah dan membuat salinan zonal data baru untuk memulihkan redundansi.

Kehilangan Zona

Ketersediaan dasar resource komputasi di zona tertentu tidak cukup untuk memenuhi SLA waktu beroperasi 99,99% BigQuery. Oleh karena itu, BigQuery menyediakan redundansi zona otomatis untuk slot data dan komputasi. Meskipun tidak umum terjadi, gangguan zona dalam waktu singkat dapat terjadi. Namun, otomatisasi BigQuery akan melakukan failover kueri ke zona lain dalam waktu satu atau dua menit setelah gangguan parah. Kueri yang sedang berlangsung mungkin tidak akan segera dipulihkan, tetapi kueri yang baru dikeluarkan akan segera dipulihkan. Hal ini akan termanifestasi karena kueri yang sedang berlangsung yang memerlukan waktu lama untuk diselesaikan sementara kueri yang baru dikeluarkan dapat selesai dengan cepat.

Meskipun suatu zona tidak tersedia untuk jangka waktu yang lebih lama, kehilangan data tidak akan terjadi karena BigQuery menulis data secara sinkron ke dua zona. Jadi, bahkan saat terjadi kehilangan di level zona, pelanggan tidak akan mengalami gangguan layanan.

Jenis kegagalan

Ada dua jenis kegagalan, kegagalan ringan dan kegagalan berat.

Kegagalan ringan adalah kekurangan operasional saat hardware tidak hancur. Contohnya meliputi kegagalan daya, partisi jaringan, atau kerusakan mesin. Secara umum, BigQuery tidak boleh kehilangan data jika terjadi kegagalan sementara.

Kegagalan besar adalah kekurangan operasional saat hardware hancur. Kegagalan berat lebih parah daripada kegagalan ringan. Contoh kegagalan berat mencakup kerusakan akibat banjir, serangan teroris, gempa bumi, dan badai.

Ketersediaan dan ketahanan

Saat membuat set data BigQuery, Anda memilih lokasi untuk menyimpan data. Lokasi ini adalah salah satu dari berikut:

  • Wilayah: lokasi geografis tertentu, seperti Iowa (us-central1) atau Montréal (northamerica-northeast1).
  • Multi-region: area geografis luas yang berisi dua atau beberapa tempat geografis, seperti Amerika Serikat (US) atau Eropa (EU).

Dalam kedua kasus tersebut, BigQuery secara otomatis menyimpan salinan data Anda di dua zona Google Cloud yang berbeda dalam satu region di lokasi yang dipilih.

Selain redundansi penyimpanan, BigQuery juga mempertahankan kapasitas komputasi yang berlebihan di beberapa zona. Dengan menggabungkan penyimpanan redundan dan komputasi di berbagai zona ketersediaan, BigQuery memberikan ketersediaan tinggi dan ketahanan.

Jika terjadi kegagalan tingkat mesin, BigQuery akan terus berjalan dengan penundaan tidak lebih dari beberapa milidetik. Semua kueri yang sedang berjalan akan terus diproses. Jika terjadi kegagalan zona ringan atau berat, kemungkinan tidak akan ada kehilangan data. Namun, kueri yang sedang berjalan mungkin gagal dan harus dikirim ulang. Kegagalan zona ringan, seperti akibat pemadaman listrik, transformator yang hancur, atau partisi jaringan, merupakan jalur yang telah teruji dengan baik dan secara otomatis dimitigasi dalam beberapa menit.

Kegagalan regional ringan, seperti hilangnya konektivitas jaringan di seluruh region, akan mengakibatkan hilangnya ketersediaan hingga wilayah tersebut kembali online, tetapi tidak mengakibatkan hilangnya data. Kegagalan regional berat, misalnya, jika bencana menghancurkan seluruh region, dapat mengakibatkan hilangnya data yang disimpan di region tersebut. BigQuery tidak secara otomatis menyediakan cadangan atau replika data Anda di region geografis lain. Anda dapat membuat salinan set data lintas region untuk meningkatkan strategi pemulihan dari bencana.

Untuk mempelajari lokasi set data BigQuery lebih lanjut, baca artikel Pertimbangan lokasi.

Skenario: Hilangnya wilayah

BigQuery tidak menawarkan ketahanan atau ketersediaan dalam peristiwa hilangnya region fisik yang sangat tidak mungkin terjadi sebelumnya. Hal ini berlaku untuk konfigurasi "region dan multi-region". Oleh karena itu, mempertahankan ketahanan dan ketersediaan di bawah skenario semacam itu memerlukan perencanaan pelanggan. Dalam kasus kehilangan sementara, seperti pemadaman jaringan, ketersediaan redundan harus dipertimbangkan jika SLA 99,99% BigQuery tidak dianggap memadai.

Untuk menghindari hilangnya data saat terjadi kehilangan regional yang destruktif, Anda perlu mencadangkan data ke lokasi geografis lain. Misalnya, Anda dapat mengekspor snapshot data ke Google Cloud Storage secara berkala di region lain yang berbeda secara geografis. Hal ini dapat dilakukan seperti yang dijelaskan dalam Kasus penggunaan pemrosesan data batch.
Dalam kasus multi-region BigQuery, Anda harus menghindari pencadangan ke region dalam cakupan multi-region. Misalnya, jangan cadangkan data Anda yang ada di AS ke region us-central1. Region dan multi-region mungkin menggunakan domain gagal yang sama dan mengalami nasib yang sama ketika terjadi bencana. Sebagai gantinya, cadangkan data ke region non-AS, seperti northamerica-northeast1. Jika persyaratan residensi data mengharuskan cadangan disimpan di AS, sebaiknya Anda menyambungkan dua region seperti us-central1 dan us-east1.

Untuk menghindari ketidaktersediaan yang diperpanjang, Anda harus menyediakan replika dan slot di dua lokasi BigQuery yang terpisah secara geografis. Serupa dengan di atas, hindari penggabungan region dan multi-region, karena keduanya mungkin memiliki nasib yang sama saat terjadi bencana.

Arsitektur yang paling andal untuk penyiapan yang redundan region adalah menjalankan hot-hot, yang juga disebut sebagai aktif-aktif. Ini berarti beban kerja Anda berjalan secara paralel di region utama dan sekunder. Meskipun lebih mahal, hal ini memastikan bahwa region sekunder mendapatkan verifikasi berkelanjutan dan akan berfungsi jika Anda perlu melakukan failover. Jika ketersediaan selama pemadaman layanan regional tidak menjadi masalah, pencadangan data ke region lain akan memastikan ketahanan.

Skenario: Penghapusan tidak disengaja atau kerusakan data

Berdasarkan arsitektur kontrol konkurensi multiversi BigQuery, BigQuery mendukung perjalanan waktu. Dengan fitur ini, Anda dapat membuat kueri data dari waktu mana pun selama tujuh hari terakhir. Hal ini memungkinkan pemulihan data secara mandiri yang salah dihapus, diubah, atau rusak dalam jangka waktu 7 hari. Perjalanan waktu bahkan dapat digunakan pada tabel yang telah dihapus.

BigQuery juga mendukung kemampuan untuk membuat snapshot tabel. Dengan fitur ini, Anda dapat secara eksplisit mencadangkan data dalam region yang sama untuk waktu yang lebih lama dari periode perjalanan 7 hari. Snapshot hanyalah sebuah operasi metadata dan tidak menghasilkan byte penyimpanan tambahan. Meskipun dapat menambahkan perlindungan terhadap penghapusan yang tidak disengaja, hal ini tidak meningkatkan ketahanan data.

Kasus penggunaan: Analisis real-time

Dalam kasus penggunaan ini, data streaming diserap dari log endpoint ke BigQuery secara terus-menerus. Perlindungan terhadap ketidaktersediaan BigQuery yang diperluas untuk seluruh region memerlukan replikasi data dan slot penyediaan secara terus-menerus di region yang berbeda. Mengingat arsitekturnya tahan terhadap ketidaktersediaan BigQuery akibat penggunaan Pub/Sub dan Dataflow di jalur penyerapan, tingkat redundansi yang tinggi ini mungkin tidak sepadan dengan biaya.

Dengan asumsi pengguna telah mengonfigurasi data BigQuery di us-east4 untuk diekspor setiap malam dengan menggunakan tugas ekspor ke Cloud Storage pada kelas Archive Storage di us-central1. Hal ini memberikan pencadangan yang andal andai terjadi kehilangan data yang drastis di us-east4. Dalam hal ini, Toleransi Jumlah Data yang Hilang (Recovery Point Objective/RPO) adalah 24 jam, karena cadangan yang terakhir diekspor dapat berusia hingga 24 jam dalam kasus terburuk. Batas Waktu Pemulihan (Recovery Time Objective/RTO) kemungkinan adalah hari, karena data perlu dipulihkan dari cadangan Cloud Storage ke BigQuery di us-central1. Jika BigQuery akan disediakan di region yang berbeda dari tempat cadangan ditempatkan, data harus ditransfer ke region ini terlebih dahulu. Perhatikan juga bahwa kecuali Anda telah membeli slot redundan di region pemulihan terlebih dahulu, mungkin ada penundaan tambahan saat menyediakan kapasitas BigQuery yang diperlukan, bergantung pada jumlah yang diminta.

Kasus penggunaan: Pemrosesan data batch

Untuk kasus penggunaan ini, sangat penting untuk bisnis bahwa laporan harian diselesaikan sebelum batas waktu tetap yang harus dikirim ke badan pengatur. Menerapkan redundansi dengan menjalankan dua instance terpisah dari seluruh pipeline pemrosesan kemungkinan akan sepadan. Penggunaan dua region terpisah, misalnya us-west1 dan us-east4, memberikan pemisahan geografis dan dua domain kegagalan independen jika suatu region tidak tersedia lagi atau bahkan kemungkinan terjadi hilangnya region permanen.

Dengan asumsi bahwa laporan perlu dikirim tepat sekali, kita harus merekonsiliasi kasus yang diharapkan dari kedua pipeline yang berhasil diselesaikan. Strategi yang wajar adalah memilih hasil dari penyelesaian pipeline terlebih dahulu, misalnya dengan memberi tahu topik Pub/Sub jika berhasil. Atau, timpa hasilnya dan buat versi ulang objek Cloud Storage. Jika pipeline yang nanti selesai menulis data rusak, Anda dapat memulihkannya dengan memulihkan versi yang ditulis oleh pipeline yang diselesaikan terlebih dahulu dari Cloud Storage.

Penanganan error

Berikut adalah praktik terbaik untuk mengatasi error yang memengaruhi keandalan.

Mencoba lagi permintaan API yang gagal

Klien BigQuery, termasuk library klien dan alat partner, harus menggunakan backoff eksponensial terpotong saat mengeluarkan permintaan API. Artinya, jika menerima error sistem atau error kuota, klien harus mencoba lagi permintaan tersebut hingga beberapa kali, tetapi dengan interval backoff yang acak dan meningkat.

Menggunakan metode percobaan ulang ini akan membuat aplikasi Anda jauh lebih andal saat menghadapi error. Bahkan dalam kondisi operasi normal, Anda dapat melihat bahwa urutan satu dari sepuluh ribu permintaan akan gagal, seperti yang dijelaskan dalam SLA ketersediaan 99,99% BigQuery. Dalam kondisi abnormal, tingkat error ini dapat meningkat. Namun, jika error didistribusikan secara acak, strategi backoff eksponensial dapat memitigasi semua kasus, kecuali kasus yang paling parah.

Jika Anda mengalami skenario ketika permintaan terus-menerus gagal dengan error 5XX, Anda harus mengeskalasikan ke Dukungan Google Cloud. Pastikan untuk mengomunikasikan dengan jelas dampak kegagalan tersebut pada bisnis Anda sehingga masalah tersebut dapat diatasi dengan benar. Di sisi lain, jika permintaan terus-menerus gagal dengan error 4XX, masalah tersebut harus dapat diatasi dengan perubahan pada aplikasi Anda. Baca pesan error untuk mengetahui detailnya.

Contoh logika backoff eksponensial

Logika backoff eksponensial mencoba ulang kueri atau permintaan dengan meningkatkan waktu tunggu antar-percobaan ulang hingga waktu backoff maksimum. Contoh:

  1. Buat permintaan ke BigQuery.

  2. Jika permintaan gagal, tunggu 1 + random_number_milliseconds detik dan coba lagi permintaan tersebut.

  3. Jika permintaan gagal, tunggu 2 + random_number_milliseconds detik dan coba lagi permintaan tersebut.

  4. Jika permintaan gagal, tunggu 4 + random_number_milliseconds detik dan coba lagi permintaan tersebut.

  5. Dan seterusnya, hingga (maximum_backoff).

  6. Terus tunggu dan coba ulang hingga jumlah maksimum percobaan ulang, tetapi jangan tambah waktu tunggu antar-percobaan ulang.

Perhatikan hal-hal berikut:

  • Waktu tunggu adalah min(((2^n)+random_number_milliseconds), maximum_backoff), dengan n bertambah 1 untuk setiap iterasi (permintaan).

  • random_number_milliseconds adalah jumlah acak milidetik yang kurang dari atau sama dengan 1.000. Pengacakan ini membantu menghindari situasi saat banyak klien disinkronkan dan semua mencoba lagi secara bersamaan, sehingga mengirimkan permintaan dalam gelombang yang disinkronkan. Nilai random_number_milliseconds dihitung ulang setelah setiap permintaan coba lagi.

  • Interval backoff maksimum (maximum_backoff) biasanya 32 atau 64 detik. Nilai yang sesuai untuk maximum_backoff bergantung pada kasus penggunaan.

Klien dapat terus mencoba ulang setelah mencapai waktu backoff maksimum. Percobaan ulang setelah tahap ini tidak perlu terus meningkatkan waktu backoff. Misalnya, jika klien menggunakan waktu backoff maksimum 64 detik, setelah mencapai nilai ini, klien dapat terus mencoba lagi setiap 64 detik. Pada saat tertentu, klien seharusnya dicegah untuk mencoba ulang tanpa batas waktu.

Waktu tunggu antara percobaan ulang dan jumlah percobaan ulang bergantung pada kasus penggunaan dan kondisi jaringan Anda.

Mencoba lagi penyisipan tugas yang gagal

Jika semantik penyisipan tepat satu kali sangat penting bagi aplikasi Anda, ada pertimbangan tambahan saat menyisipkan tugas. Cara mencapai semantik paling banyak sekali bergantung pada WriteDisposition yang Anda tentukan. Disposisi tulis memberi tahu BigQuery hal yang harus dilakukan saat menemukan data yang sudah ada dalam tabel: gagal, timpa, atau tambahkan.

Dengan disposisi WRITE_EMPTY atau WRITE_TRUNCATE, hal ini dicapai hanya dengan mencoba kembali penyisipan atau eksekusi tugas yang gagal. Hal ini karena semua baris yang diserap oleh tugas ditulis secara atomik ke tabel.

Dengan disposisi WRITE_APPEND, klien harus menentukan ID tugas agar tidak mencoba menambahkan data yang sama untuk kedua kalinya. Cara ini berfungsi karena BigQuery menolak permintaan pembuatan tugas yang mencoba menggunakan ID dari tugas sebelumnya. Hal ini mencapai semantik paling banyak satu kali untuk ID tugas tertentu. Kemudian, Anda dapat mencapai tepat satu kali dengan mencoba ulang menggunakan ID tugas baru yang dapat diprediksi setelah mengonfirmasi dengan BigQuery bahwa semua upaya sebelumnya telah gagal.

Dalam beberapa kasus, klien API atau klien HTTP mungkin tidak menerima konfirmasi bahwa tugas disisipkan karena masalah sementara atau gangguan jaringan. Saat penyisipan dicoba lagi, permintaan tersebut gagal dengan status=ALREADY_EXISTS (code=409 dan reason="duplicate"). Status tugas yang ada dapat diambil dengan panggilan ke jobs.get. Setelah status tugas yang ada adalah retrieved, pemanggil dapat menentukan apakah tugas baru dengan ID TUGAS baru harus dibuat atau tidak.

Kasus penggunaan dan persyaratan keandalan

BigQuery mungkin menjadi komponen penting dari berbagai arsitektur. Bergantung pada kasus penggunaan dan arsitektur yang di-deploy, berbagai persyaratan ketersediaan, performa, atau keandalan lainnya mungkin perlu dipenuhi. Untuk tujuan panduan ini, mari kita pilih dua kasus penggunaan dan arsitektur utama yang akan dibahas secara mendetail.

Analisis real-time

Contoh pertama adalah pipeline pemrosesan data peristiwa. Dalam contoh ini, peristiwa log dari endpoint diserap menggunakan Pub/Sub. Dari sana, pipeline Dataflow streaming akan menjalankan beberapa operasi pada data sebelum menulisnya ke BigQuery menggunakan Storage Write API. Data ini kemudian digunakan untuk kueri ad hoc, misalnya, untuk membuat ulang urutan peristiwa yang mungkin telah menghasilkan hasil endpoint tertentu, dan untuk memasukkan data ke dasbor yang mendekati real-time guna memungkinkan deteksi tren dan pola dalam data melalui visualisasi.

Contoh ini mengharuskan Anda mempertimbangkan beberapa aspek keandalan. Karena persyaratan keaktualan data menyeluruh cukup tinggi, latensi proses penyerapan sangat penting. Setelah data ditulis ke BigQuery, keandalan dianggap sebagai kemampuan pengguna untuk mengajukan kueri ad-hoc dengan latensi yang konsisten dan dapat diprediksi, serta memastikan bahwa dasbor yang memanfaatkan data mencerminkan informasi yang benar-benar terbaru.

Pemrosesan data batch

Contoh kedua adalah arsitektur batch processing yang didasarkan pada kepatuhan terhadap peraturan di industri jasa keuangan. Persyaratan utamanya adalah memberikan laporan harian kepada badan pengatur dengan batas waktu setiap malam yang tetap. Selama proses batch setiap malam yang menghasilkan laporan selesai sebelum batas waktu ini, proses tersebut dianggap cukup cepat.

Data harus tersedia di BigQuery dan digabungkan dengan sumber data lain untuk dasbor, analisis, dan pada akhirnya pembuatan laporan PDF. Penyerahan laporan ini tepat waktu dan tanpa kesalahan adalah persyaratan bisnis yang sangat penting. Oleh karena itu, memastikan keandalan penyerapan data dan pembuatan laporan dengan benar dan dalam jangka waktu yang konsisten untuk memenuhi tenggat waktu yang diperlukan adalah kuncinya.

Langkah selanjutnya