File Storage (Google Drive/Dropbox) ডিজাইন
- ●বড় file ছোট ছোট chunk-এ ভেঙে object storage (S3)-এ রাখা হয়, আর metadata আলাদা database-এ থাকে।
- ●Content hash দিয়ে deduplication করলে একই file বারবার আপলোড হলেও storage একবারই খরচ হয়।
- ●Sync, versioning আর permission—এই তিনটা feature file storage-কে নিছক upload tool থেকে আলাদা করে দেয়।
ভাবো তুমি Google Drive বা Dropbox বানাচ্ছো। কোটি কোটি মানুষ ছবি, ভিডিও, document রাখবে, একাধিক device থেকে দেখবে, share করবে। সমস্যাটা শুধু "file রাখা" নয়—file sync, version, permission আর storage খরচ সামলানোই আসল চ্যালেঞ্জ। চলো advanced ইন্টারভিউ-এর মতো করে এটা ডিজাইন করি।
১. সমস্যা বোঝা (Requirements)
Functional requirements:
- File upload ও download।
- একাধিক device-এর মধ্যে sync—এক জায়গায় বদলালে সব জায়গায় আপডেট হবে।
- Versioning—পুরোনো version ফিরিয়ে আনা যাবে।
- Sharing ও permission—অন্যকে view/edit access দেওয়া।
- Deduplication—একই file বারবার রাখলে storage অপচয় হবে না।
Non-functional requirements:
- Durability: file কখনো হারানো যাবে না (99.999999999% — eleven nines)।
- Availability: যেকোনো সময় file পাওয়া যাবে।
- Scalability: petabyte পরিমাণ data, কোটি কোটি user।
- Bandwidth efficiency: sync-এ যেন পুরো file বারবার না যায়।
২. স্কেল আন্দাজ (Estimation)
মোট user = 5 কোটি (50,000,000)
DAU = 1 কোটি (10,000,000)
প্রতি user গড় file = 200টি, গড় size 1 MB
গড় storage/user = 200 MB
মোট storage (raw) = 50M × 200 MB = 10 PB (পেটাবাইট)
Deduplication-এর পরে (~30% সাশ্রয়) ≈ 7 PB
দৈনিক upload:
ধরা যাক প্রতি DAU/দিন 2টি নতুন file × 1 MB
= 10M × 2 MB = 20 TB/দিন নতুন data
QPS (metadata read, peak):
বেশিরভাগ request হলো "আমার file list দাও"
ধরা যাক DAU প্রতিদিন 50 বার সিঙ্ক চেক করে
= 10M × 50 / 86,400 ≈ 5,800 read QPS (peak ~3x ≈ 17,400)
মূল পর্যবেক্ষণ: এটা read-heavy (file দেখা > আপলোড), আর storage-heavy। তাই metadata read fast রাখা আর storage সস্তা রাখা—দুটোই গুরুত্বপূর্ণ।
৩. API ডিজাইন
POST /v1/files/upload-init
{ "name": "report.pdf", "size": 5242880, "chunk_hashes": ["h1","h2",...] }
→ { "file_id": "f_99", "missing_chunks": ["h2"] } // dedup: শুধু এগুলো লাগবে
PUT /v1/chunks/{chunk_hash} // একটা chunk আপলোড (S3-তে সরাসরি signed URL দিয়েও হতে পারে)
POST /v1/files/{file_id}/commit // সব chunk এলে file চূড়ান্ত করা
GET /v1/files/{file_id} // download (chunk list + signed URL)
GET /v1/files?folder=root // file list (sync)
POST /v1/files/{file_id}/share // permission দেওয়া
GET /v1/files/{file_id}/versions // version history
লক্ষ করো upload-init-এ আমরা client থেকে chunk-এর hash চাই, তারপর শুধু missing_chunks ফেরত দিই। এটাই deduplication-এর জাদু—যা আগে থেকে আছে তা আবার আপলোড করতে হয় না।
৪. ডেটা মডেল
| Table/Collection | প্রধান field | কাজ |
|---|---|---|
files | file_id, owner_id, name, folder_id, latest_version, size | file-এর metadata |
file_versions | version_id, file_id, version_no, chunk_list, created_at | প্রতিটি version-এর chunk তালিকা |
chunks | chunk_hash, storage_url, ref_count, size | dedup-এর জন্য chunk registry |
permissions | file_id, user_id, role (view/edit) | sharing |
devices | device_id, user_id, last_sync_cursor | sync track করা |
SQL নাকি NoSQL?
files,permissions,file_versions→ SQL (PostgreSQL)। কারণ permission আর folder hierarchy-তে relation ও transaction দরকার। কে কোন file দেখতে পাবে—এটা ভুল হলে privacy ফাঁস।chunksregistry → NoSQL / key-value (DynamoDB), কারণ এটা শুধু hash → location lookup, কোটি কোটি entry, আর fast point-read দরকার।- আসল file content → Object Storage (S3), কোনো DB নয়।
ব্যাপারটা ভাবো একটা লাইব্রেরির মতো। বইগুলো (file content) থাকে বিশাল গুদামে (S3)। আর সামনে থাকে একটা ছোট কার্ড-ক্যাটালগ (metadata DB)—যেখানে লেখা কোন বই কোন তাকে, কে লিখেছে, কে ধার নিতে পারবে। তুমি কখনো গুদামে ঢুকে খোঁজো না; ক্যাটালগ দেখে তাক নম্বর পাও, তারপর সোজা সেই বই তোলো। catalog ছোট ও দ্রুত, গুদাম বড় ও সস্তা।
৫. হাই-লেভেল ডিজাইন
মূল components:
- Client app — file-কে chunk-এ ভাঙে, hash বের করে, sync চালায়।
- API / Metadata service — file metadata, permission, version সামলায়।
- Block/Chunk service — chunk store ও dedup করে।
- Object Storage (S3) — আসল chunk-এর data।
- Metadata DB — file-এর তথ্য।
- Notification/Sync service — অন্য device-কে "বদল হয়েছে" জানায়।
Upload flow ধাপে ধাপে:
- Client file-কে নির্দিষ্ট size-এর (যেমন 4 MB) chunk-এ ভাঙে এবং প্রতিটির content hash বের করে।
- Client
upload-initডাকে, সব chunk hash পাঠায়। - Metadata service
chunksregistry-তে দেখে কোন hash আগে থেকে আছে—শুধু missing chunk ফেরত দেয়। - Client শুধু missing chunk-গুলো S3-তে (signed URL দিয়ে সরাসরি) আপলোড করে।
- প্রতিটি নতুন chunk-এর জন্য
chunksregistry-তে entry যোগ হয়, পুরোনো hash-এরref_countবাড়ে। - Client
commitডাকে; metadata service নতুন version বানিয়ে chunk_list সংরক্ষণ করে। - Sync service অন্য device-গুলোকে notify করে।
৬. গভীরে (Deep Dive)
Chunking আর Sync
Chunking মানে বড় file-কে ছোট ছোট নির্দিষ্ট মাপের টুকরোয় ভাঙা। এর তিনটা বড় লাভ:
- Resumable upload: ১ GB file আপলোডের মাঝে net গেলে পুরোটা আবার নয়, যে chunk বাকি শুধু সেটা পাঠাও।
- Delta sync: ১০০ MB document-এর একটা লাইন বদলালে শুধু সেই একটা chunk আবার আপলোড হয়, পুরো file নয়। bandwidth বিশাল বাঁচে।
- Parallel transfer: একাধিক chunk একসাথে আপলোড/ডাউনলোড করে গতি বাড়ানো যায়।
Sync-এর জন্য client একটা cursor রাখে (শেষ কোন পরিবর্তন দেখেছে)। sync-এ সে server-কে cursor পাঠায়, server তার পর থেকে যা বদলেছে শুধু সেই metadata ফেরত দেয়—long polling বা WebSocket দিয়ে real-time notify-ও করা যায়।
Deduplication আর Content Hash
প্রতিটি chunk-এর data থেকে আমরা Content Hash (যেমন SHA-256—data থেকে তৈরি একটা unique fingerprint) বের করি। দুটো chunk-এর content এক হলে তাদের hash-ও এক। তাই আপলোডের আগে hash মিলিয়ে দেখি—আগে থাকলে আবার store করি না, শুধু ref_count বাড়াই।
এর ফল: একই PowerPoint যদি ১০০ জন আপলোড করে, storage-এ থাকে একবার। এটা storage খরচ ৩০-৫০% কমিয়ে দিতে পারে।
Deduplication-এ Ref Count (কতজন এই chunk ব্যবহার করছে) ঠিকমতো সামলানো জরুরি। একজন file delete করলেই chunk মুছে ফেললে অন্যের file ভেঙে যাবে! তাই delete-এ ref_count কমাও; শুধু ref_count = 0 হলে তবেই garbage collection দিয়ে S3 থেকে মুছবে। আর এই counter update concurrent-safe হতে হবে, নইলে race condition-এ data হারাবে।
Versioning ও Permission
প্রতিবার commit-এ নতুন file_versions row তৈরি হয়, যাতে আগের chunk_list অক্ষত থাকে। যেহেতু chunk dedup হয়, নতুন version শুধু বদলে যাওয়া chunk-এর জন্য জায়গা নেয়—পুরো file নয়। তাই version history সস্তা।
Permission চেক হতে হবে প্রতিটি download/metadata request-এ। folder share করলে ভেতরের file-ও inherit করবে—এই hierarchy fast resolve করতে permission cache (Redis) রাখা যায়।
৭. বটলনেক ও স্কেলিং
- Metadata DB hotspot: read-heavy বলে read replica আর Redis cache দিয়ে file-list query দ্রুত করো। বড় হলে user_id দিয়ে sharding।
- S3 throughput: S3 নিজেই বিশাল স্কেলযোগ্য; client সরাসরি signed URL দিয়ে আপলোড করায় আমাদের server bandwidth bottleneck হয় না।
- Thundering herd on sync: কোটি client একসাথে poll করলে চাপ। long polling/WebSocket + jitter দিয়ে ছড়িয়ে দাও।
- Hot chunk: কোনো জনপ্রিয় file (viral video) বারবার download হলে CDN দিয়ে edge-এ cache করো।
- Durability: S3 নিজে multiple zone-এ replicate করে eleven-nines durability দেয়; metadata DB-ও backup ও replicate করতে হবে।
৮. সারসংক্ষেপ
আমরা একটা file storage system বানালাম যেখানে—client file-কে chunk-এ ভেঙে content hash বের করে, dedup করে শুধু missing chunk S3-তে যায়, metadata আলাদা DB-তে থাকে, আর versioning ও permission relational DB সামলায়। Sync হয় cursor + delta দিয়ে, storage বাঁচে dedup-এ।
ইন্টারভিউয়ার দেখতে চান তুমি কি metadata ও content-কে আলাদা করতে পেরেছ, chunking-এর সুবিধা (resume + delta sync) বুঝেছ, আর dedup-এর ref_count trap (delete-এ data না হারানো) ধরতে পেরেছ। এই তিনটা ঠিকঠাক বললে advanced প্রশ্নেও তুমি শক্ত অবস্থানে।
মিনি কুইজ
1. বড় file ছোট chunk-এ ভাঙার প্রধান সুবিধা কী?
2. Deduplication-এ content hash কীভাবে কাজে লাগে?
3. Metadata আর actual file content আলাদা জায়গায় রাখা হয় কেন?