GH GambleHub

Multipart-експорти та великі вивантаження

1) Коли потрібні «великі» експорти і що важливо

Сценарії: фінансові звіти, вивантаження активності користувачів, аудит/регулятори, BI-вивантаження, партнерські каталоги, резервні копії. Ключові вимоги:
  • Узгодженість даних (snapshot/точка в часі).
  • Прохідність за обсягом (паралельний запис/читання, потокова серіалізація).
  • Відновлюваність (resumable) і часткова доставка.
  • Цілісність (checksum) і верифікованість (маніфест).
  • Безпека/PII (маскування, шифрування, контроль доступу).
  • Управління вартістю (компресія, тайм-аути, CDN, TTL).

2) Формати даних: плюси/мінуси

CSV - компактно, швидко писати/читати; мінуси: екранування, типи втрачаються. Добре для табличних звітів.
JSON Lines (JSONL) - по рядку на об'єкт, зручний для стрімінгу і часткової вибірки; мінуси: об'єм.
Parquet/Avro - колонкові/схемні формати, стиснення і predicate pushdown; ідеальні для аналітики і великих даних.
Mixed: JSONL для API-завантаження → офлайн-конверсія в Parquet.

Компресія: 'gzip '/' zstd'( краще). Для дуже великих обсягів - спліт-архіви (за ~ 128-512 МБ на частину).

3) Узгодженість: Як отримати «знімок»

БД: транзакційна ізоляція REPEATABLE READ/SNAPSHOT; для потоків - логічні слоти реплікації або позначка'watermark'( макс.'updated _ at '/версія).
Event sourcing: експорт по offset журналу.
Зрізи: «повний» експорт + «дельти» (наступні вивантаження змін з моменту'watermark').

4) Розбиття на частини (multipart/chunking)

4. 1 Види «multipart»

Upload (до нас): multipart/form-data (дрібні файли), S3 Multipart Upload (MPU )/GCS Resumable (великі).
Download (від нас): HTTP Range ('bytes = start-end'),'multipart/byteranges'( кілька діапазонів в одній відповіді), «zip of parts», каталоги в об'єктному сторі.

4. 2 Стратегії розбиття

За розміром (наприклад, 256 МБ на частину).
По ключу/даті (шардування по'tenant _ id','YYYY/MM/DD').
За таблицею/сутністю (окремі файли на типи).

Баланс: частини 64-512 МБ добре скачуються паралельно і не перегрівають пам'ять.

5) API-архітектура експорту (асинхронна модель)

Кроки:

1.'POST/exports'→ завдання в черзі (метадані: формат, фільтри, шифрування, термін життя).

2. Воркери будують snapshot, стримлять дані і пишуть частини в об'єктне сховище.

3. Генерують маніфест (JSON) з переліком частин, розмірами, checksum, версією схеми.

4.'GET/exports/{ id}'повертає статус і посилання (і) на частини/pre-signed URL.

5. `GET /exports/{id}/manifest. json'- машина правди для верифікації/дозавантаження.

Приклад маніфесту:
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) Відновлювані вивантаження (resumable)

HTTP Range: клієнт довантажує «хвіст» файлу: `Range: bytes=241172480-`.
Декілька діапазонів: `Range: bytes = 0-999,2000-2999'→ відповідь'Content-Type: multipart/byteranges`.
Клієнтська стратегія: паралельні «воркери» на частини, верифікація'sha256'кожної, ретраї з експоненціальним backoff.
CDN: підтримка Range, вимкнена буферизація великих відповідей.

7) Великі завантаження до нас (resumable upload)

S3 Multipart Upload: клієнти завантажують частини (5-5000), сервер збирає'CompleteMultipartUpload'.
GCS Resumable: один сеанс, зміщення - клієнт може продовжувати з'Content-Range'.
TUS (протокол) - незалежний відновлюваний аплоад поверх HTTP.

Патерн B2B: віддаємо pre-signed URL для аплоаду частин безпосередньо в стор, а метадані - в наш API.

8) Компресія, шифрування, цілісність

Компресія: 'zstd'кращий (краще ratio/швидкість). Стискайте кожну частину окремо (зручніше відновлювати/кешувати).

Шифрування:
  • На проводі: TLS 1. 2+.
  • У спокої: server-side KMS (SSE-KMS) або client-side (AES-256-GCM) з обгорткою ключа (key wrapping).
  • Ніколи не кладіть «сирий» ключ в маніфест.
  • Checksum: мінімум SHA-256 на частину + загальний для всього набору. Перевіряйте на клієнті перед ack.

9) Інтеграція з периметром: NGINX/CDN

NGINX (Range + великі таймаути + відключити буферизацію):
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;
}
}
Заголовки відповідей:
  • `Content-Disposition: attachment; filename="export_2025-10-31_part-00000. parquet. zst"`
  • 'ETag '/' If-Range'для коректного довантаження.
  • 'Cache-Control'( наприклад,'private, max-age = 3600') для персональних вивантажень.

10) Безпека та комплаєнс

Автентифікація/авторизація: видача експортів тільки власнику/ролям; тимчасові посилання (pre-signed) з коротким TTL.
PII: маскування/псевдонімізація; в маніфесті - тільки технічні поля.
GDPR/локальні регулятори: видалення експортів по TTL, аудит скачувань, заборона крос-регіональної видачі без підстави.
Rate limiting & quotas: обмежити кількість одночасних експортів і загальний обсяг на добу/місяць (per-tenant).
Анти-скрапінг: САР/бот-фільтри на видачу посилань, обмеження діапазонів (макс. паралельних частин).

11) Спостережуваність і експлуатація

Метрики:
  • `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`
Логи/аудит:
  • Хто створив експорт, фільтри, watermark, список скачувань (IP/UA/час).
  • Хеші частин і звірка на стороні клієнта (підтвердження).
Трейсинг:
  • Спани на етапи: snapshot → serialize → upload part → finalize.

12) Продуктивність і вартість

Паралельність: генеруйте кілька частин одночасно (N воркерів), але лімітуйте I/O.
Пам'ять: потокова серіалізація (ітератори, курсори БД, чанки по 4-16 МБ).
Дедуп: для часто повторюваних експортів розумний cache of parts за фільтрами/хешу.
CDN: вигідно для «загальних» публічних наборів; для персональних - обережно (безпека/PII).

13) Приклади інтерфейсів

13. 1 Створення експорту (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"}
}
Відповідь:
json
{
"id":"exp_2025_10_31_001",
"status":"queued",
"estimated_parts": 12,
"manifest_url": "/exports/exp_2025_10_31_001/manifest. json"
}

13. 2 Видача частини з Range

http
GET /exports/exp_.../part-00003. parquet. zst
Range: bytes=1048576-

13. 3 Псевдокод воркера

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) Патерни дельта-експортів

Повний експорт раз в N (день/тиждень) + дельти щогодини по'updated _ at> watermark'.
На стороні споживача: застосувати дельти по порядку, верифікуючи'version '/' seq'.
Зберігайте останній watermark в споживачі і в маніфесті.

15) Анти-патерни

Генерація експорту в запиті (синхронно) - таймаути і OOM.
Один гігантський файл без розбиття - неможливість відновлення/паралельного закачування.
Відсутність checksum і маніфесту - не можна довести цілісність.
Видача постійних публічних посилань на персональні дані.
Буферизація SSE/CDN або відключені Range - ламає «дозавантаження».
Експорт «брудних» даних (без snapshot/ізоляції).

16) Чек-лист впровадження

  • Формат і компресія: CSV/JSONL/Parquet + `zstd/gzip`.
  • Узгодженість: транзакційний snapshot або watermark/offset.
  • Розбиття: частини 64-512 МБ, паралельна генерація і скачування.
  • Маніфест: список частин, розміри, SHA-256, версія схеми, watermark.
  • Відновлення: HTTP Range, підтримка'multipart/byteranges', клієнтські ретраї.
  • Безпека: pre-signed URLs, TTL, шифрування (KMS/AEAD), маскування PII.
  • Ліміти/квоти: per-tenant, добові обсяги, число активних джоб.
  • Спостережуваність: метрики джоб/частин, аудит скачувань, алерти на checksum-fail.
  • Вартість: CDN для публічних наборів, TTL і авто-cleanup в сторі.
  • Runbooks/Game Days: обриви мережі, недоступність стора, перегрів БД, збій KMS.

17) Game Days (плейбуки)

Обрив мережі при скачуванні: клієнт повинен продовжити з'Range'.
Збій завантаження однієї частини: ретрай частини без перестворення всього експорту.
Падіння воркера: джоба поновлюється з останнього непідтвердженого чанка.
KMS недоступний: безпечна деградація (пауза генерації, не випускати незашифровано).
Зростання даних × 2: перевірити час генерації, перерозподілити паралелізм, не вбити БД.

18) Підсумки

Надійні великі вивантаження - це асинхронна архітектура + розбиття на частини + відновлення + цілісність, що перевіряється. Робіть snapshot, пишіть частини паралельно, публікуйте маніфест з checksum, підтримуйте HTTP Range і короткоживучі посилання. Продумайте безпеку, ліміти і спостережуваність - і гігабайтні експорти перестануть бути нічним кошмаром для команд і користувачів.

Contact

Зв’яжіться з нами

Звертайтеся з будь-яких питань або за підтримкою.Ми завжди готові допомогти!

Telegram
@Gamble_GC
Розпочати інтеграцію

Email — обов’язковий. Telegram або WhatsApp — за бажанням.

Ваше ім’я необов’язково
Email необов’язково
Тема необов’язково
Повідомлення необов’язково
Telegram необов’язково
@
Якщо ви вкажете Telegram — ми відповімо й там, додатково до Email.
WhatsApp необов’язково
Формат: +код країни та номер (наприклад, +380XXXXXXXXX).

Натискаючи кнопку, ви погоджуєтесь на обробку даних.