Exporturi multipartite și încărcări mari
1) Când sunt necesare exporturi „mari” și ce este important
Scenarii: rapoarte financiare, încărcări de activități ale utilizatorilor, audituri/autorități de reglementare, încărcări BI, directoare partenere, backup-uri. Cerințe cheie:- Consistența datelor (instantaneu/punct în timp).
- Pasabilitatea în volum (scriere/citire paralelă, serializare în flux).
- Livrare regenerabilă și parțială.
- Integritate (sumă de control) și verificabilitate (manifest).
- Securitate/PII (mascare, criptare, control acces).
- Managementul costurilor (compresie, timeout, CDN, TTL).
2) Formate de date: argumente pro/contra
CSV - compact, rapid de scris/citit; contra: ecranare, tipuri pierdute. Bun pentru rapoarte tabelare.
JSON Lines (JSONL) - prin linie per obiect, convenabil pentru streaming și eșantionare parțială; contra: volum.
Parchet/Avro - formate de coloane/circuite, compresie și prezice pushdown; ideal pentru analiză și date mari.
Mixt: JSONL pentru descărcare API → conversie offline la parchet.
Compresie: "gzip "/" zstd' (mai bine). Pentru volume foarte mari - arhive divizate (~ 128-512 MB pe parte).
3) Consistență: Cum să obțineți un „instantaneu”
DB: REPETABIL READ/SNAPSHOT izolarea tranzacțională; pentru fire, sloturi de replicare logice sau filigran (max. 'update _ at'/versiune).
Sursa evenimentului: export prin offset log.
Felii: "full' export +" deltas "(încărcări ulterioare de modificări de la" filigran ").
4) Multipart/chunking
4. 1 Tipuri de „multipart”
Încărcați (la noi): multipart/form-data (fișiere mici), S3 Multipart Upload (MPU )/GCS Resumable (mare).
Descărcați (de la noi): HTTP Range ('bytes = start-end'),' multipart/byteranges '(mai multe intervale într-un singur răspuns), "zip of parts', directoare în stiva de obiecte.
4. 2 Strategii de divizare
După dimensiune (de exemplu, 256 MB pe parte).
După cheie/dată (partajare după 'chiriaş _ id',' AAAA/LL/ZZ ').
Prin tabel/entitate (fișiere individuale pe tip).
Balanță: Părți de 64-512 MB descarcă bine în paralel și nu supraîncălzesc memoria.
5) Arhitectura API de export (model asincron)
Pași:1. 'POST/exports' → loc de muncă în coadă (metadate: format, filtre, criptare, durată de viață).
2. Lucrătorii construiesc instantanee, transmit date și scriu piese pentru a obiecta stocarea.
3. Generați un manifest (JSON) cu o listă de părți, dimensiuni, sumă de control, versiune schemă.
4. 'GET/exports/{ id}' returnează starea și link-ul către părți ale URL-ului/pre-semnat.
5. 'GET/exports/{ id }/manifest. json '- masina adevar pentru verificare/reincarcare.
Exemplu de manifestare: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) Reluabil
HTTP Range: clientul încarcă „coada” fișierului: 'Range: bytes = 241172480-'.
Intervale multiple: 'Interval: octeți = 0-999,2000-2999' → 'Tip de conținut: răspuns multipart/byteranges'.
Strategia clientului: paralel „lucrători” în părți, verificarea „sha256” din fiecare, retrai cu backoff exponențial.
CDN: Suport pentru interval, tamponare de răspuns mare dezactivată.
7) Descărcări mari la noi (încărcare reluabilă)
S3 Multipart Încărcați: clienții descarcă piese (5-5000), serverul colectează 'CompleteMultipartUpload'.
GCS Resumable - o sesiune, compensează - clientul poate continua cu 'Content-Range'.
TUS (protocol) este un appload regenerabil independent pe partea de sus a HTTP.
Model B2B: trimitem URL-ul pre-semnat pentru încărcarea pieselor direct la magazin și metadatele la API-ul nostru.
8) Compresie, criptare, integritate
Compresie: "zstd' preferat (raport/viteză mai bună). Comprimați fiecare parte separat (este mai convenabil să reînnoiți/cache).
Criptare:- Pe fir: TLS 1. 2+.
- În rest: server-side KMS (SSE-KMS) sau client-side (AES-256-GCM) cu cheie de ambalare.
- Nu puneți niciodată o cheie „brută” într-un manifest.
- Suma de control: SHA-256 minimă per parte + comună pentru întregul set. Verificați pe client înainte de ack.
9) Integrarea perimetrului: NGINX/CDN
NGINX (Interval + intervale lungi de timp + dezactivați tamponarea):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;
}
}
Anteturi de răspuns:
- "Dispunerea conținutului: atașament; fișier = "export _ 2025-10-31 _ part-00000. parchet. zst'
- "ETag "/" If-Range 'pentru încărcarea corectă.
- „Cache-Control” (de exemplu, „privat, max-age = 3600”) pentru încărcări personale.
10) Siguranță și conformitate
Autentificare/autorizare: eliberarea exporturilor numai proprietarului/rolurilor; pre-semnat cu scurt TTL.
PII: mascare/aliasare; în manifest - numai domenii tehnice.
GDPR/autorități locale de reglementare: ștergerea exporturilor de către TTL, auditul descărcărilor, interzicerea emisiunii transregionale fără motiv.
Limitarea tarifelor și cotelor: limitarea numărului de exporturi simultane și a volumului total pe zi/lună (per chiriaș).
Anti-răzuire: filtre CAP/bot pentru emiterea de legături, limitarea intervalelor (piese max paralele).
11) Observabilitate și funcționare
Măsurători:- 'export _ jobs _ total {status}' (coadă/alergare/succes/eșec/expirat)
- 'export _ bytes _ total', 'export _ part _ duration _ ms {p50, p95, p99}'
- 'download _ range _ requires _ total', 'CV _ total', 'checksum _ fail _ total'
- 'storage _ cost _ estimate' и 'egress _ bytes _ cdn'
- Cine a creat exportul, filtre, filigran, descărcare listă (IP/UA/timp).
- Piese de hash-uri și reconcilierea partea clientului (confirmări).
- Spans: instantaneu → serializați → încărcați o parte → finalizați.
12) Performanță și cost
Paralelism: Generați mai multe părți simultan (N lucrători), dar limitați I/O.
Memorie: streaming serialization (iteratoare, cursoare de baze de date, bucăți de 4-16 MB).
Dedup: pentru exporturi repetate frecvent, memorie cache inteligentă a pieselor prin filtre/hash.
CDN: benefic pentru grupuri publice „generice”; pentru personal - prudență (siguranță/PII).
13) Exemple de interfețe
13. 1 Creează export (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"}
}
Răspuns:
json
{
"id":"exp_2025_10_31_001",
"status":"queued",
"estimated_parts": 12,
"manifest_url": "/exports/exp_2025_10_31_001/manifest. json"
}
13. 2 Partea de emitere cu Range
http
GET /exports/exp_.../part-00003. parquet. zst
Range: bytes=1048576-
13. 3 Vorker pseudocod
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) Modele de export Delta
Export complet o dată în N (zi/săptămână) + delta în fiecare oră prin 'update _ at> filigran'.
Pe partea consumatorului, aplicați delta pentru a verifica „versiunea ”/„ seq”.
Păstrați ultimul filigran în consumator și în manifest.
15) Anti-modele
Generarea exportului în cerere (sincron) - timeout și OOM.
Un fișier gigant fără divizare este incapacitatea de a relua/descărcare paralelă.
Lipsa sumei de control și a manifestului - nu puteți dovedi integritatea.
Emiterea de linkuri publice permanente către date cu caracter personal.
Tamponarea SSE/CDN sau cu handicap Range - rupe „reîncărcarea”.
Exportați date murdare (fără instantaneu/izolare).
16) Lista de verificare a implementării
- Format și compresie: CSV/JSONL/Parchet + 'zstd/gzip'.
- Consistență: instantaneu tranzacțional sau filigran/offset.
- Partiționare: 64-512 MB piese, generare paralelă și descărcare.
- Manifest: lista de piese, dimensiuni, SHA-256, versiune schema, filigran.
- Reînnoire: HTTP Range, suport „multipart/byteranges”, retraiele clienților.
- Securitate: URL-uri pre-semnate, TTL, criptare (KMS/AEAD), mascare PII.
- Limite/cote: per-chiriaș, volume zilnice, număr de locuri de muncă active.
- Observabilitate: job/part metrics, download audits, checksum-fail alerts.
- Cost: CDN pentru seturi publice, TTL și auto-curățare în magazin.
- Runbooks/Zilele jocului: pauze de rețea, indisponibilitate magazin, supraîncălzirea bazei de date, eșec KMS.
17) Zilele jocului (playbooks)
Cădere de rețea în timpul descărcării: Clientul trebuie să continue cu 'Range'.
O parte nu a reușit să încarce: retraiul piesei fără a recrea întregul export.
Locul de muncă se reia cu ultima bucată neconfirmată.
KMS indisponibil: degradare sigură (pauză de generare, nu eliberați necriptat).
Creșterea datelor × 2: verificați timpul de generare, redistribuiți paralelismul, nu ucideți baza de date.
18) Totaluri
Descărcările mari fiabile sunt arhitectura asincronă + partiționarea + reînnoirea + integritatea verificabilă. Luați un instantaneu, scrieți părți în paralel, publicați un manifest cu suma de control, sprijiniți HTTP Range și link-uri de scurtă durată. Gândiți-vă prin securitate, limite și observabilitate - și exporturile gigabyte vor înceta să fie un coșmar pentru echipe și utilizatori.