Esportazioni multipart e grandi scarichi
1) Quando è necessario esportare «grandi» e cosa è importante
Script: report finanziari, caricamento utente, controllo/regolatori, download BI, cartelle di partner, backup. Requisiti chiave:- Coerenza dei dati (snapshot/point nel tempo).
- Viabilità volumica (scrittura/lettura parallela, serializzazione in streaming).
- Rinnovabile (resumable) e spedizione parziale.
- Integrità (checksum) e validità (manifesto).
- Sicurezza/PII (occultamento, crittografia, controllo degli accessi).
- Gestione del costo (compressione, timeout, CDN, TTL).
2) Formati di dati: pro/contro
CSV - compatto, scrivere/leggere rapidamente; contro: schermatura, i tipi vengono persi. Bene per i tabulati.
JSON Lines (JSONL) - riga per oggetto, facile da usare per lo streaming e il campionamento parziale; contro: volume.
Parquet/Avro - formati colinvertebrati/schemi, compressione e predicate pushdown; Ideale per gli analisti e i dati di grandi dimensioni.
Mixed: JSONL per il caricamento API della conversione offline in Parket.
Compressione: «gzip »/« zstd» (migliore). Per volumi molto elevati, gli archivi split (da 128 a 512 MB per parte).
3) Coerenza: come ottenere un'istantanea "
Database: isolamento transazionale REPEATABLE READ/SNAPSHOT; per i thread: slot logiche di replica o segno «watermark» (max «updated _ at »/versione).
Event source - Esporta per offset il registro.
Taglio: esportazione «completa» + «delta» (successivi download di modifiche da «watermark»).
4) Ripartizione (multipart/chunking)
4. 1 Viste multipart
Upload (a noi): multiplart/form-data (file piccoli), S3 Multipart Upload (MPU )/GCS Resumable (grandi).
Download (da noi): HTTP Range ('byties = start-end'), 'multipart/byteranges' (più intervalli nella stessa risposta), 'zip of parts', cartelle nello store degli oggetti.
4. 2 Strategie di ripartizione
Per dimensioni (ad esempio 256 MB per parte).
Per chiave/data («tenant _ id», «YYYY/MM/DD»).
Per tabella/entità (singoli file per tipo).
Bilanciamento: le parti 64-512 MB si scaricano bene in parallelo e non surriscaldano la memoria.
5) Architettura API di esportazione (modello asincrona)
Passi:1. 'POST/exports', processo in coda (metadati: formato, filtri, crittografia, durata della vita).
2. I worker costruiscono snapshot, cancellano i dati e scrivono le parti nel deposito oggetti.
3. Generano un manifesto (JSON) con un elenco di parti, dimensioni, checksum, versione dello schema.
4. 'GET/exports/{ id}' restituisce lo stato e il riferimento (e) alle parti/pre-signed URL.
5. `GET /exports/{id}/manifest. json'è una macchina della verità per la verifica/controllo.
Esempio di manifesto:json
{
"export_id": "exp_2025_10_31_001",
"created_at": "2025-10-31T14:23:00Z",
"schema": "orders_v3",
"format": "parquet+zstd",
"parts": [
{"name":"part-00000. parquet. zst","size":268435456,"sha256":"...","url":"...","range":"bytes=0-268435455"},
{"name":"part-00001. parquet. zst","size":241172480,"sha256":"...","url":"..."}
],
"total_bytes": 509607936,
"encryption": {"type":"AES-256-GCM","key_id":"kms/keys/exp"},
"watermark": {"type":"updated_at","value":"2025-10-31T00:00:00Z"}
}
6) Scarichi rinnovabili (resumable)
HTTP Range: il client esegue la coda del file: 'Range: byties = 241172480'.
Più intervalli: «Range: byties = 0-999,2000-2999», risposta «Content-Type: multipart/byteranges».
Strategia dei clienti: «worker» paralleli a pezzi, verifica «sha256» ciascuno, retrai con backoff esponenziale.
CDN - Supporto Range, buffer di grandi risposte disattivato.
7) Grandi download a noi (resumable upload)
S3 Multiplart Upload: i client caricano parti (5-5000) e il server raccoglie «CompleteMultipartUpload».
GCS Resumable: una sessione, offset - il client può continuare con Content-Range.
Il TUS (protocollo) è un appload indipendente e rinnovabile sopra HTTP.
Pattern B2B: assegniamo l'URL pre-signed per l'applicazione delle parti direttamente allo store e i metadati alla nostra API.
8) Compressione, crittografia, integrità
Compressione: «zstd» è preferibile (migliore ratio/velocità). Comprimi ciascuna parte separatamente (è più facile riprendere/memorizzare la cache).
Crittografia:- TLS 1 sul filo. 2+.
- In linea: server-side KMS (SSE-KMS) o client-side (AES-256-GCM) con avvolgimento chiave (key wrapping).
- Non mettere mai la chiave cruda nel manifesto.
- Checksum: minimo SHA-256 per parte + totale per l'intero set. Controllare il client prima di ack.
9) Integrazione con perimetro: NGINX/CDN
NGINX (Range + grandi timeout + disattivare buffering):nginx server {
listen 443 ssl http2;
server_name downloads. example. com;
location /exports/ {
proxy_buffering off;
proxy_request_buffering off;
proxy_read_timeout 3600s;
add_header Accept-Ranges bytes;
proxy_pass http://export-backend;
}
}
Titoli di risposta:
- `Content-Disposition: attachment; filename="export_2025-10-31_part-00000. parquet. zst"`
- «ETAG »/« If-Range» per un corretto controllo.
- «Cache-Control» (ad esempio, «private, max-age = 3600») per i download personali.
10) Sicurezza e compliance
Autenticazione/autorizzazione: rilascio di esportazioni solo al proprietario/ruolo; collegamenti temporanei (pre-signed) con TTL breve.
PII: maschera/alias; nel manifesto ci sono solo campi tecnici.
GDPR/regolatori locali: rimozione di esportazioni TTL, controllo dei download, divieto di rilascio crociato-regionale senza motivo.
Rate limiting & quote: limita il numero di esportazioni simultanee e il volume totale al giorno/mese (per-tenant).
Anti-scraping: filtri SAR/Bot per il rilascio di riferimenti, limiti di intervalli (parti parallele massime).
11) Osservabilità e funzionamento
Metriche:- `export_jobs_total{status}` (queued/running/succeeded/failed/expired)
- `export_bytes_total`, `export_part_duration_ms{p50,p95,p99}`
- `download_range_requests_total`, `resumes_total`, `checksum_fail_total`
- `storage_cost_estimate` и `egress_bytes_cdn`
- Chi ha creato l'esportazione, filtri, watermark, l'elenco dei download (IP/UA/tempo).
- Hash parti e compressione sul lato client (conferma).
- Span per fasi: snapshot → serialize → upload part → finalize.
12) Prestazioni e costi
Parallelità: generate più parti contemporaneamente (N worker), ma limitate I/O.
Memoria: seriatizzazione in streaming (iteratori, cursori di database, chanci da 4 a 16 MB).
Per le esportazioni frequenti, cache of parts intelligente per filtri/hashtag.
CDN: utile per i set pubblici «condivisi» personale - attenzione (sicurezza/PII).
13) Esempi di interfaccia
13. 1 Creazione esportazione (REST)
http
POST /exports
Content-Type: application/json
Authorization: Bearer <token>
{
"format": "parquet+zstd",
"filters": {"date_from":"2025-10-01","date_to":"2025-10-31","tenant":"acme"},
"split_size_mb": 256,
"encryption": {"mode":"server-side-kms","key_id":"kms/keys/exp"}
}
Risposta:
json
{
"id":"exp_2025_10_31_001",
"status":"queued",
"estimated_parts": 12,
"manifest_url": "/exports/exp_2025_10_31_001/manifest. json"
}
13. 2 Rilascio parte con Range
http
GET /exports/exp_.../part-00003. parquet. zst
Range: bytes=1048576-
13. 3 Pseudocode worker
pseudo snapshot = db. begin_snapshot()
for shard in plan_shards(snapshot):
part_stream = encode_stream(shard. rows, format="parquet", compress="zstd")
url = object_store. upload_stream(part_stream, part_name, encryption=KMS)
manifest. add(part_name, size, sha256, url)
write_manifest(manifest)
14) Pattern delta-export
Esportazione completa una volta in N (giorno/settimana) + delta ogni ora à updated _ at> watermark '.
Dal lato del consumatore, applicare i delta in ordine, con la validazione dì version "/" seq ".
Conservare l'ultimo watermark nel consumatore e nel manifesto.
15) Anti-pattern
Generazione di esportazione nella query (sincrona) - Timeout e OOM.
Un file gigantesco non diviso è l'impossibilità di riprendere o scaricare parallelamente.
L'assenza di checksum e di un manifesto non può essere dimostrata.
Rilascia collegamenti pubblici costanti ai dati personali.
Buffer SSE/CDN o Range disattivate - Rompe il dosaggio.
Esporta dati «sporchi» (senza snapshot/isolante).
16) Assegno-foglio di implementazione
- Formato e compressione: CSV/JSONL/Parket + 'zstd/gzip'.
- Coerenza: snapshot transazionale o watermark/offset.
- Partizione: parti 64-512 MB, generazione e download paralleli.
- Manifesto: elenco di parti, dimensioni, SHA-256, versione schema, watermark.
- Riapertura: HTTP Range, supporto «multipart/byteranges», retrai client.
- Protezione: pre-signed URLs, TTL, crittografia (KMS/AEAD), maschera PII.
- Limiti/quote: per-tenant, quantità giornaliere, numero di attivi.
- Osservabilità: metriche delle parti, controllo dei download, alert per checksum-fail.
- Costo: CDN per set pubblici, TTL e auto-cleanup nello store.
- Runbooks/Game Days - Scollature della rete, indisponibilità dello store, surriscaldamento del database, errore di KMS.
17) Game Days (playbook)
Dirottamento della rete durante il download: il client deve continuare con Range.
Impossibile caricare una parte, il retro della parte senza ritardare l'intera esportazione.
La caduta del Worker, il jobs, riparte dall'ultima chat non confermata.
KMS non disponibile: degrado sicuro (pausa di generazione, non crittografia).
Crescita dei dati x 2: controllare i tempi di generazione, ridistribuire il parallelismo, non uccidere il database.
18) Riepilogo
Grandi carichi di lavoro affidabili: architettura asincrona + ripartenza + integrità verificabile. Fai snapshot, scrivi parti parallele, pubblichi un manifesto con checksum, supporta HTTP Range e collegamenti brevi. Pensate alla sicurezza, ai limiti e all'osservabilità - e gli esporti gigabyte non saranno più un incubo per le squadre e gli utenti.