-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
313 lines (254 loc) · 13.9 KB
/
Copy pathMakefile
File metadata and controls
313 lines (254 loc) · 13.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
FLINK_REST := http://localhost:8082
SQL_GATEWAY := http://localhost:8083
.PHONY: up down logs clean status \
gen-logs gen-pause gen-resume \
topic-describe consumer-lag \
ch ch-query ch-ingestion ch-freshness ch-lag \
check-clocks \
flink flink-jobs flink-logs flink-sql flink-submit flink-cancel \
flink-p2 flink-p3 flink-submit-p5 \
minio \
sr sr-query sr-init sr-p4 sr-freshness \
sr-p5-init sr-p5 sr-p5-freshness \
sr-p6-init sr-p6-status sr-p6 sr-p6-freshness \
stream-init stream-flink-submit stream-cancel \
stream-sr-status stream-ch-status stream-probe-logs \
ui grafana prometheus smoke-test
# Start all Phase 1 services
up:
docker compose up -d --build
# Stop all services (keep volumes)
down:
docker compose down
# Stop all services and wipe volumes (full reset)
clean:
docker compose down -v
# Follow all logs
logs:
docker compose logs -f
# Service health overview
status:
docker compose ps
# Generator throughput stats
gen-logs:
docker compose logs -f generator
# Pause / resume data generation without losing container state
gen-pause:
docker compose stop generator
@echo "Generator paused. Run 'make gen-resume' to restart."
gen-resume:
docker compose start generator
@echo "Generator resumed."
# Describe the transactions topic
topic-describe:
docker compose exec broker kafka-topics --describe \
--bootstrap-server broker:29092 \
--topic transactions
# List consumer groups and their lag
consumer-lag:
docker compose exec broker kafka-consumer-groups --bootstrap-server broker:29092 \
--list | xargs -I{} docker compose exec broker \
kafka-consumer-groups --bootstrap-server broker:29092 --describe --group {}
# ── ClickHouse (Phase 2) ──────────────────────────────────────────────────────
# Open interactive ClickHouse client (analytics database)
ch:
docker compose exec clickhouse clickhouse-client --database analytics
# Run a SQL query inline: make ch-query Q="SELECT count() FROM transactions"
ch-query:
docker compose exec clickhouse clickhouse-client --database analytics --query "$(Q)"
# Check how many rows have been ingested and the current compression ratio
ch-ingestion:
docker compose exec clickhouse clickhouse-client --database analytics --query \
"SELECT table, formatReadableQuantity(sum(rows)) AS rows, \
formatReadableSize(sum(data_compressed_bytes)) AS compressed \
FROM system.parts WHERE database='analytics' AND active GROUP BY table"
# Run Q3 freshness probe (freshness_lag_ms, pipeline_lag_ms, total_rows)
ch-freshness:
docker compose exec clickhouse clickhouse-client --database analytics --query \
"SELECT max(event_time) AS newest, now64(3) AS now, \
dateDiff('millisecond', max(event_time), now64(3)) AS freshness_lag_ms, \
dateDiff('millisecond', max(event_time), max(ingest_time)) AS pipeline_lag_ms, \
count() AS total_rows FROM analytics.transactions"
# Show Kafka Engine consumer status and any exceptions
ch-lag:
docker compose exec clickhouse clickhouse-client --query \
"SELECT consumer_id, num_messages_read, num_rebalance_assignments, \
num_rebalance_revocations, exceptions.text \
FROM system.kafka_consumers WHERE database='analytics' FORMAT Vertical"
# ── Flink + Fluss (Phase 3) ───────────────────────────────────────────────────
# Open Flink UI
flink:
open http://localhost:8082
# List all Flink jobs and their status via REST
flink-jobs:
curl -s $(FLINK_REST)/jobs | python3 -m json.tool
# Follow JobManager + TaskManager logs
flink-logs:
docker compose logs -f flink-jobmanager flink-taskmanager
# Open interactive Flink SQL client connected to SQL Gateway (not embedded)
flink-sql:
docker compose exec flink-jobmanager /opt/flink/bin/sql-client.sh -e http://localhost:8083
# Run P2 benchmark queries (Fluss Union Read — hot + cold) via SQL Gateway
flink-p2:
docker compose exec -T flink-jobmanager bash -c \
'cat /sql/benchmark_p2.sql | /opt/flink/bin/sql-client.sh -e http://localhost:8083'
# Run P3 benchmark queries (Fluss cold lake only — Parquet scan) via SQL Gateway
flink-p3:
docker compose exec -T flink-jobmanager bash -c \
'cat /sql/benchmark_p3.sql | /opt/flink/bin/sql-client.sh -e http://localhost:8083'
# Cancel all RUNNING Flink jobs via REST API
flink-cancel:
@curl -sf $(FLINK_REST)/jobs | \
python3 -c "import sys,json; [print(j['id']) for j in json.load(sys.stdin)['jobs'] if j['status']=='RUNNING']" | \
xargs -I{} curl -sf -X PATCH "$(FLINK_REST)/jobs/{}?mode=cancel" || true
@echo "All running jobs cancelled."
# Submit tiering JAR via Flink REST API (upload + run — no docker exec needed)
flink-submit-tiering:
@echo "Uploading Fluss tiering JAR..."
@JAR_ID=$$(docker compose exec -T flink-jobmanager \
curl -sf -X POST -F "jarfile=@/opt/flink/opt/fluss-flink-tiering-0.9.1-incubating.jar" \
http://localhost:8081/jars/upload | \
python3 -c "import sys,json; print(json.load(sys.stdin)['filename'].split('/')[-1])"); \
echo "Submitting tiering job ($$JAR_ID)..."; \
docker compose exec -T flink-jobmanager \
curl -sf -X POST http://localhost:8081/jars/$$JAR_ID/run \
-H "Content-Type: application/json" \
-d '{"flinkConfiguration":{"parallelism.default":"1","execution.checkpointing.interval":"60000","execution.checkpointing.mode":"AT_LEAST_ONCE"},"programArgsList":["--fluss.bootstrap.servers","coordinator-server:9123","--datalake.format","paimon","--datalake.paimon.metastore","filesystem","--datalake.paimon.warehouse","s3://fluss/paimon-warehouse","--datalake.paimon.s3.endpoint","http://minio:9000","--datalake.paimon.s3.access-key","minioadmin","--datalake.paimon.s3.secret-key","minioadmin","--datalake.paimon.s3.path.style.access","true","--s3.endpoint","http://minio:9000","--s3.access-key","minioadmin","--s3.secret-key","minioadmin","--s3.path-style-access","true","--s3.region","us-east-1","--s3.assumed.role.arn","arn:aws:iam::000000000000:role/minioadmin","--s3.assumed.role.sts.endpoint","http://minio:9000"]}' | \
python3 -c "import sys,json; d=json.load(sys.stdin); print('Tiering job ID:', d.get('jobid','ERROR'))"
# Submit Kafka→Fluss SQL ingestion job via SQL Gateway REST API
# Note: pipe via stdin — sql-client -f silently skips in gateway mode
flink-submit-sql:
docker compose exec -T flink-jobmanager bash -c \
'cat /sql/01_kafka_to_fluss.sql | /opt/flink/bin/sql-client.sh -e http://localhost:8083'
# Submit both jobs: tiering JAR + SQL ingestion (cancel existing jobs first)
flink-submit: flink-submit-tiering flink-submit-sql
# Submit P5 Flink job: Fluss hot layer → StarRocks PK table (streaming write)
# Run make sr-p5-init first to create the StarRocks target table.
flink-submit-p5:
docker compose exec -T flink-jobmanager bash -c \
'cat /sql/02_fluss_to_starrocks.sql | /opt/flink/bin/sql-client.sh -e http://localhost:8083'
# Open MinIO console (cold storage for Fluss datalake tier)
minio:
open http://localhost:9001
# ── StarRocks (Phase 4) ───────────────────────────────────────────────────────
# Open interactive StarRocks MySQL client
sr:
docker compose exec starrocks mysql -h 127.0.0.1 -P 9030 -u root
# Run a SQL query inline: make sr-query Q="SELECT count(*) FROM paimon_catalog.analytics.transactions"
sr-query:
docker compose exec starrocks mysql -h 127.0.0.1 -P 9030 -u root -e "$(Q)"
# Create the Paimon external catalog (run once after make up)
sr-init:
docker compose exec -T starrocks mysql -h 127.0.0.1 -P 9030 -u root \
< docker/starrocks/init/01_catalog.sql
@echo "StarRocks Paimon catalog created."
# Run P4 benchmark queries (StarRocks → Paimon cold lake)
sr-p4:
docker compose exec -T starrocks mysql -h 127.0.0.1 -P 9030 -u root \
< docker/starrocks/queries/benchmark_p4.sql
# ── StarRocks (Phase 4 — P5: Flink stream write) ─────────────────────────────
# Create StarRocks target table for P5 (run once, before flink-submit-p5)
sr-p5-init:
docker compose exec -T starrocks mysql -h 127.0.0.1 -P 9030 -u root \
< docker/starrocks/init/03_p5_table.sql
@echo "StarRocks transactions_p5 table created."
# Run P5 benchmark queries (Q1/Q2/Q3 on Flink-fed native PK table)
sr-p5:
docker compose exec -T starrocks mysql -h 127.0.0.1 -P 9030 -u root \
< docker/starrocks/queries/benchmark_p5.sql
# Q3 freshness probe on P5 table
sr-p5-freshness:
docker compose exec starrocks mysql -h 127.0.0.1 -P 9030 -u root -e \
"SELECT MAX(event_time) AS newest_event_time, NOW() AS query_time, \
TIMESTAMPDIFF(SECOND, MAX(event_time), NOW()) * 1000 AS freshness_lag_ms, \
TIMESTAMPDIFF(SECOND, MAX(event_time), MAX(ingest_time)) * 1000 AS pipeline_lag_ms, \
COUNT(*) AS total_rows \
FROM analytics.transactions_p5"
# ── StarRocks (Phase 4 — P6: Routine Load) ───────────────────────────────────
# Create analytics DB, transactions_p6 table, and Routine Load job (run once)
sr-p6-init:
docker compose exec -T starrocks mysql -h 127.0.0.1 -P 9030 -u root \
< docker/starrocks/init/02_p6_setup.sql
@echo "P6 table + Routine Load job created."
# Show Routine Load job state (running, lag, error rows)
sr-p6-status:
docker compose exec starrocks mysql -h 127.0.0.1 -P 9030 -u root -e \
"SHOW ROUTINE LOAD FOR analytics.transactions_p6_load\G"
# Run P6 benchmark queries (Q1/Q2/Q3 on native StarRocks PK table)
sr-p6:
docker compose exec -T starrocks mysql -h 127.0.0.1 -P 9030 -u root \
< docker/starrocks/queries/benchmark_p6.sql
# Q3 freshness probe on P6 table
sr-p6-freshness:
docker compose exec starrocks mysql -h 127.0.0.1 -P 9030 -u root -e \
"SELECT MAX(event_time) AS newest_event_time, NOW() AS query_time, \
TIMESTAMPDIFF(SECOND, MAX(event_time), NOW()) * 1000 AS freshness_lag_ms, \
TIMESTAMPDIFF(SECOND, MAX(event_time), MAX(ingest_time)) * 1000 AS pipeline_lag_ms, \
COUNT(*) AS total_rows \
FROM analytics.transactions_p6"
# Q3 freshness probe only
sr-freshness:
docker compose exec starrocks mysql -h 127.0.0.1 -P 9030 -u root -e \
"SELECT MAX(event_time) AS newest_event_time, NOW() AS query_time, \
TIMESTAMPDIFF(SECOND, MAX(event_time), NOW()) * 1000 AS freshness_lag_ms, \
TIMESTAMPDIFF(SECOND, MAX(event_time), MAX(ingest_time)) * 1000 AS pipeline_lag_ms, \
COUNT(*) AS total_rows \
FROM paimon_catalog.analytics.transactions"
# ── Streaming benchmark (benchmark 2) ────────────────────────────────────────
#
# Prerequisite order:
# 1. make flink-cancel — free task slots (streaming benchmark needs ~6)
# 2. make sr-query Q="PAUSE ROUTINE LOAD FOR analytics.transactions_p6_load"
# — avoid concurrent ingestion contention on single BE
# 3. make stream-init — create transactions_s table + start Routine Load
# 4. make stream-flink-submit — submit all 3 streaming queries as one Flink job
# 5. Wait ~60s for steady state, then watch probe metrics in Grafana
# Create StarRocks transactions_s table + start tuned Routine Load (run once)
stream-init:
docker compose exec -T starrocks mysql -h 127.0.0.1 -P 9030 -u root \
< docker/starrocks/init/04_streaming_benchmark.sql
@echo "StarRocks transactions_s table + Routine Load created."
# Submit Flink streaming benchmark job (Q-A, Q-B, Q-C as single STATEMENT SET)
stream-flink-submit:
docker compose exec -T flink-jobmanager bash -c \
'cat /sql/06_streaming_benchmark.sql | /opt/flink/bin/sql-client.sh -e http://localhost:8083'
# Cancel the Flink streaming benchmark job (and all other running jobs)
stream-cancel: flink-cancel
# Show StarRocks Routine Load status for streaming benchmark
stream-sr-status:
docker compose exec starrocks mysql -h 127.0.0.1 -P 9030 -u root -e \
"SHOW ROUTINE LOAD FOR analytics.transactions_s_load\G"
# Show ClickHouse streaming Kafka consumer status
stream-ch-status:
docker compose exec clickhouse clickhouse-client --query \
"SELECT consumer_id, num_messages_read, exceptions.text \
FROM system.kafka_consumers WHERE database='analytics' \
AND consumer_id LIKE '%ch-streaming%' FORMAT Vertical"
# Follow probe container logs
stream-probe-logs:
docker compose logs -f probe
# ── Clock skew verification ───────────────────────────────────────────────────
# All containers must agree on UTC wall-clock to within ~5ms for accurate
# freshness_lag_ms and pipeline_lag_ms measurements.
# On macOS Docker Desktop containers share the same VM kernel clock, so
# true drift is zero; this check catches timezone misconfiguration.
check-clocks:
@echo "UTC wall-clock across containers (should all match to <5ms):"
@for svc in broker clickhouse generator schema-registry; do \
t=$$(docker compose exec -T $$svc date -u +"%Y-%m-%dT%H:%M:%S.%3NZ" 2>/dev/null || echo "unavailable"); \
printf " %-20s %s\n" "$$svc" "$$t"; \
done
# ── UIs ───────────────────────────────────────────────────────────────────────
# Open UIs (macOS)
ui:
open http://localhost:8090
grafana:
open http://localhost:3000
prometheus:
open http://localhost:9090
# Produce a single test message to verify setup
smoke-test:
echo '{"event_id":"test-1","user_id":1,"amount":9.99,"region":"us-east-1","event_type":"purchase","event_time":"2025-01-01T00:00:00.000Z"}' | \
docker compose exec -T broker kafka-console-producer \
--bootstrap-server broker:29092 \
--topic transactions