95. Studi Kasus: Aplikasi Analitik Sederhana dengan Streaming
Seiring pertumbuhan data yang semakin pesat, kebutuhan untuk memproses dan menganalisis data secara real-time juga meningkat. Pendekatan pemrosesan batch tradisional, di mana data dikumpulkan dan diproses secara berkala, sering kali tidak cukup untuk kebutuhan bisnis modern, terutama untuk kasus seperti monitoring transaksi, fraud detection, atau analitik moda transportasi. Oleh karena itu, streaming data muncul sebagai solusi yang efektif.
Pada artikel ini, saya akan membagikan studi kasus pembangunan aplikasi analitik sederhana menggunakan streaming. Studi kasus ini kita ambil dari dunia nyata namun disederhanakan agar mudah dipahami dan direplikasi. Kita akan membahas desain arsitektur, contoh kode, hingga simulasi, tabel hasil, serta diagram alur menggunakan mermaid. Pembaca diharapkan memiliki gambaran implementasi aplikasi streaming end-to-end.
Studi Kasus: Analitik Streaming Transaksi E-commerce
Deskripsi Kasus:
Sebuah perusahaan e-commerce ingin memonitor transaksi pembayaran secara real-time untuk menganalisa rata-rata nilai transaksi tiap kota dan mendeteksi lonjakan volume transaksi. Data transaksi masuk secara terus-menerus (stream) ke sistem.
Arsitektur Solusi
Untuk studi kasus sederhana ini, kita memilih stack sebagai berikut:
- Proses streaming: Apache Kafka (messaging) dan Apache Spark Streaming (analitik)
- Visualisasi hasil: Konsol dan tabel sederhana
Berikut diagram alurnya:
flowchart LR
User(Platform User) -->|Transaksi| API[API Order Service]
API -->|Push data| Kafka[(Kafka Topic)]
Kafka -->|Ingest| Spark[Spark Streaming Job]
Spark -->|Hasil Analitik| Output[Console/Tabel Hasil]
Skema Data Transaksi
Setiap transaksi yang masuk memiliki struktur data berikut (format JSON):
{
"order_id": "OID123456",
"created_at": "2024-06-20T10:14:38Z",
"user_id": "USER789",
"city": "Jakarta",
"amount": 250000.0
}
Kunci utama dalam studi kasus ini adalah field city dan amount.
Simulasi Data Streaming
Sebelum masuk ke kode analitik, kita membutuhkan simulasi data transaksi yang akan dikirim ke Kafka. Untuk tujuan studi kasus, kita akan menggunakan script Python sederhana pengirim data ke Kafka.
# transaksi_producer.py
import json
import random
import time
from datetime import datetime
from kafka import KafkaProducer
cities = ['Jakarta', 'Bandung', 'Surabaya', 'Medan']
producer = KafkaProducer(bootstrap_servers=['localhost:9092'])
def generate_transaksi():
return {
"order_id": f"OID{random.randint(100000, 999999)}",
"created_at": datetime.utcnow().isoformat() + 'Z',
"user_id": f"USER{random.randint(100, 999)}",
"city": random.choice(cities),
"amount": float(random.randint(50000, 500000))
}
while True:
transaksi = generate_transaksi()
producer.send('transaksi_topic', json.dumps(transaksi).encode('utf-8'))
print("Kirim:", transaksi)
time.sleep(random.uniform(0.2, 1.0)) # simulasi data stream
Proses Analitik dengan Spark Streaming
Kita menggunakan Spark Structured Streaming (Python API: PySpark) untuk membaca data dari Kafka, lalu menghitung:
- Rata-rata nilai transaksi per kota per window waktu (misal 1 menit)
- Deteksi lonjakan volume transaksi per kota (misal: volume naik lebih dari 50% window sebelumnya)
Berikut contoh kode analitiknya:
# streaming_analitik.py
from pyspark.sql import SparkSession
from pyspark.sql.functions import from_json, col, window, avg, count
from pyspark.sql.types import StructType, StringType, FloatType, TimestampType
# Skema data
schema = StructType() \
.add("order_id", StringType()) \
.add("created_at", StringType()) \
.add("user_id", StringType()) \
.add("city", StringType()) \
.add("amount", FloatType())
# Create Spark Session
spark = SparkSession.builder \
.appName("TransaksiStreamingAnalitik") \
.getOrCreate()
spark.sparkContext.setLogLevel("WARN")
# Baca stream dari Kafka
raw_df = spark \
.readStream \
.format("kafka") \
.option("kafka.bootstrap.servers", "localhost:9092") \
.option("subscribe", "transaksi_topic") \
.load()
# Parsing JSON
transaksi_df = raw_df.selectExpr("CAST(value AS STRING) as json_str") \
.select(from_json(col("json_str"), schema).alias("data")) \
.select("data.*") \
.withColumn("created_at", col("created_at").cast(TimestampType()))
# Windowed average per city
avg_df = transaksi_df \
.groupBy(
window(col("created_at"), "1 minute", "30 seconds"),
col("city")
).agg(
avg("amount").alias("avg_amount"),
count("order_id").alias("volume_transaksi")
)
query = avg_df.writeStream \
.outputMode("update") \
.format("console") \
.option("truncate", False) \
.start()
query.awaitTermination()
Output Sample (Tabel Konsol)
| window_start | window_end | city | avg_amount | volume_transaksi |
|---|---|---|---|---|
| 2024-06-20 10:14:00 | 2024-06-20 10:15:00 | Jakarta | 245000 | 8 |
| 2024-06-20 10:14:00 | 2024-06-20 10:15:00 | Bandung | 302000 | 5 |
| 2024-06-20 10:14:00 | 2024-06-20 10:15:00 | Surabaya | 198000 | 7 |
| 2024-06-20 10:14:00 | 2024-06-20 10:15:00 | Medan | 155000 | 3 |
Deteksi Lonjakan Volume Transaksi
Untuk deteksi lonjakan (spike) volume, kita perlu menyimpan volume window sebelumnya dan membandingkannya. Pada implementasi produksi, umumnya digunakan Redis, Cassandra atau stateful streaming. Namun untuk studi kasus sederhana, kita cukup menambah logika pengecekan lonjakan pada Spark Structured Streaming. Berikut ilustrasinya memakai window 1 menit rolling:
from pyspark.sql.window import Window
from pyspark.sql.functions import lag, col, expr
# Tambahkan windowed dataframe
windowed_df = avg_df
# Menggunakan lag (tidak support di Structured Streaming directly, solusi: simpan ke sink lalu proses di batch/layer lain)
# Alternatif: Tulis ke sink (contoh: database) untuk kemudian dibandingkan
# Simulasi pseudo-code:
# volume_lama = read_previous_window(city)
# lonjakan = volume_baru > 1.5 * volume_lama
Pada sistem nyata, Spark streaming biasanya push hasil ke storage (misal Redis), lalu alert logic membaca storage tersebut untuk mendeteksi spike.
Diskusi: Sisi Engineer
Sebagai engineer, beberapa pelajaran penting dari studi kasus real-time streaming ini:
- Single Source of Truth: Kafka sebagai central event log membuat sistem lebih mudah diskalakan dan fault-tolerant.
- Window dan State: Windowing pada batch interval penting untuk agregasi dan deteksi trend/spike. Namun stateful streaming membutuhkan storage/performance tuning lebih lanjut.
- Pemrosesan Late Data: Handling out-of-order/lateness sangat penting, terutama jika data berasal dari banyak sumber atau device IoT.
- Alert system (Notif): Deteksi spike volume bisa dihubungkan ke notifikasi webhook/email untuk alert dalam sistem nyata.
Diagram Alur End-to-End
sequenceDiagram
participant User as User
participant API as API Service
participant Kafka as Kafka Broker
participant Spark as Streaming Analytic
participant DB as Storage/Console
User->>API: Kirim Transaksi
API->>Kafka: Publish Event
Kafka->>Spark: Stream Data Transaction
Spark->>DB: Tulis hasil agregat/window
Spark->>Spark: Analisis Spike
Spark-->>DB: Notifikasi/Alert Lonjakan
Kesimpulan
Lewat studi kasus ini, kita melihat bagaimana pipeline sederhana streaming analitik dibangun mulai dari ingest data, pemrosesan dan agregasi real-time, hingga deteksi anomali sederhana. Pendekatan di atas bisa dipakai dan dikembangkan untuk berbagai kebutuhan, mulai dari aplikasi monitoring finansial, prediksi kebutuhan logistik, hingga IoT.
Produksi solusi streaming membutuhkan integrasi sistem yang matang, monitoring yang baik, dan penanganan berbagai edge-case seperti data duplicate, late-arriving, scaling dan lain-lain. Namun pondasinya tetap pada desain event-driven dan stateful streaming, sebagaimana dicontohkan di atas.
Semoga studi kasus ini membuka wawasan dan bisa menjadi starter kit bagi engineer yang ingin merambah dunia streaming analytics!
Silahkan eksplorasi kode contoh dan modifikasi sesuai kebutuhan proyekmu. Happy coding!