Episode ini membahas keandalan aplikasi Spark: checkpointing di Structured Streaming, perilaku fault tolerance dan recovery, state management untuk streaming jobs, serta best practices untuk aplikasi streaming jangka panjang yang berjalan tanpa henti.

Aplikasi streaming di produksi berjalan berhari-hari atau bahkan berbulan-bulan tanpa henti. Selama itu, berbagai hal bisa terjadi: node mati, jaringan putus, Kafka tidak responsif. Episode 16 ini membahas bagaimana Spark tetap andal di tengah semua itu — lewat checkpointing dan fault tolerance.
Tanpa mekanisme pemulihan, satu kegagalan kecil bisa memaksa job streaming restart dari awal, kehilangan data yang sudah diproses atau menghasilkan duplikat. Memahami cara Spark menyimpan progress dan state adalah kunci untuk membangun pipeline streaming yang bisa dipercaya.
Episode ini membahas empat hal: checkpointing di Structured Streaming, perilaku fault tolerance dan recovery, state management untuk streaming jobs, serta best practices untuk aplikasi streaming jangka panjang.
Checkpoint adalah lokasi di mana Spark menyimpan metadata pemrosesan secara berkala. Isinya mencakup:
query = df.writeStream \
.format("parquet") \
.option("path", "data/hasil") \
.option("checkpointLocation", "data/checkpoint") \
.outputMode("append") \
.start()checkpointLocation harus disimpan di penyimpanan yang bertahan lama (HDFS, S3, atau volume Kubernetes yang persisten) — bukan di local disk worker yang bisa hilang. Dari metadata inilah Spark tahu harus melanjutkan dari mana.
Aturan penting: checkpoint location tidak boleh dipakai bersama oleh dua query yang berbeda, dan tidak boleh dipakai ulang oleh query yang strukturnya berubah drastis. Jika logika berubah signifikan, gunakan lokasi checkpoint baru.
Saat aplikasi streaming dihentikan secara paksa atau node mati, alur recovery berlangsung seperti ini:
restart driver → baca checkpoint → lanjut dari offset terakhir → proses ulangSemantik pengiriman tergantung sink:
spark-submit --conf spark.sql.streaming.schemaInference=true \
--conf spark.sql.streaming.fileSink.log.deletion=true job.pyspark.sql.streaming.fileSink.log.deletion adalah salah satu konfigurasi pembersihan metadata file sink. Untuk jaminan duplikat yang lebih ketat di batch processing, kalian bisa memanfaatkan Delta Lake yang menyediakan transaksi idempoten.
Setiap agregasi ber-state (window, groupBy) menyimpan hasil sementara di memory. Watermark membantu membersihkan state yang sudah tidak relevan. Jika state membesar tanpa kendali, aplikasi bisa melambat atau memori meluap.
Untuk logika state kustom — misalnya session tracking — Spark menyediakan API mapGroupsWithState dan flatMapGroupsWithState:
import org.apache.spark.sql.streaming.GroupState
def updateState(userId: String,
events: Iterator[Event],
state: GroupState[UserState]): Iterator[Output] = {
val current = state.getOption.getOrElse(UserState.empty)
val updated = current.update(events)
state.update(updated)
Iterator(Output(userId, updated.summary))
}GroupState[UserState] menyimpan state per kunci yang dipersist secara periodik ke checkpoint. Wajib menentukan timeout agar state kunci yang tidak aktif bisa dihapus — kalau tidak, state hanya akan tumbuh.
state.setTimeoutDuration("30 minutes")state.setTimeoutDuration("30 minutes") otomatis memicu callback timeout untuk kunci yang tidak menerima event selama 30 menit — pola standar untuk sessionization.
Beberapa praktik yang menjaga aplikasi streaming tetap sehat selama berbulan-bulan:
query.stop() dan driver diberi waktu menyelesaikan penulisan batch terakhir.Saat meng-upgrade kode atau library:
1. submit query baru dengan checkpoint baru (mode uji)
2. verifikasi data tidak ganda dan sink normal
3. cutover: hentikan query lama, jalankan yang baruPola ini menghindari kegagalan di tengah malam karena perubahan yang belum teruji terhadap format checkpoint lama.
Warning
Checkpoint bukan pengganti backup data. Jika sumber data (misalnya Kafka) sudah menghapus offset lama karena retention, Spark tidak bisa membaca ulang data yang tidak ada lagi. Seimbangkan retention Kafka dengan kebutuhan recovery jangka panjang.
Episode 16 menuntaskan aspek keandalan: checkpoint menyimpan offset, state, dan metadata agar job bisa lanjut setelah kegagalan; recovery memulihkan posisi dan state secara otomatis; state management dengan mapGroupsWithState mengontrol logika kustom; dan best practices menjaga aplikasi streaming tetap sehat dalam jangka panjang.
Inti yang harus dibawa pulang:
Di episode 17 selanjutnya kita akan membahas custom extensions dan UDFs — menulis UDF, UDAF, dan UDT di Scala, Java, dan Python, custom serialization dengan Kryo, mengekstensi Spark dengan library eksternal, serta packaging library untuk dipakai ulang di banyak job.