| Problem | Likely reason | Fix |
|---|---|---|
| No rows appear in sink | Watermark not advancing | Set env.set_parallelism(1) for single-partition topic |
| Consumer reads nothing | Started at latest |
Use auto_offset_reset='earliest' |
| Duplicated counts | Topic contains old messages from prior runs | Delete/recreate topic and rerun producer |
| Flink job runs but no output | Wrong timestamp parsing | Verify TO_TIMESTAMP format matches payload |
All three Flink jobs follow the same structure:
- Create source table from Kafka (
green-trips) - Create sink table in PostgreSQL
- Execute
INSERT INTO ... SELECT ...with window aggregation - Query sink table in Postgres to validate result
Kafka stores/streams events. Flink computes continuous transformations over those events.
Kafka answers: "Can we move events reliably?" Flink answers: "Can we compute useful stateful analytics in real time?"
One of the most important things to understand about Spark is lazy evaluation. Spark doesn't actually DO anything until it absolutely has to:
Your code: What Spark does:
df = spark.read.parquet(...) β "I'll remember to read this" (no action yet)
If you've used pandas, you already know what a DataFrame is β it's a table with rows and columns. Spark DataFrames work the same way, but distributed across multiple machines:
Pandas DataFrame (lives on ONE machine):
βββββββββββββββ¬βββββββββββ¬βββββββββββ
β pickup_time β distance β fare β
NewerOlder