ইমেজ হোস্টিং সার্ভিস ডিজাইন
সমস্যাটি বোঝা
ইমেজ হোস্টিং সার্ভিসগুলো ব্যবহারকারীদের ছবি আপলোড করার, শেয়ার করার জন্য লিংক তৈরি করার, এবং সেসব ছবি মিলিয়ন মিলিয়ন দর্শকের কাছে খুব দ্রুত পৌঁছে দেওয়ার সুযোগ দেয়। ইমগুর (Imgur), ফ্লিকার (Flickr) বা সোশ্যাল মিডিয়া প্ল্যাটফর্মগুলোর পেছনে কাজ করা ইমেজ ব্যাকএন্ডগুলোর কথা ভাবুন।
চলুন আমাদের রিকয়ারমেন্টগুলো দেখে নিই:
ফাংশনাল রিকয়ারমেন্টস:
- আপলোড: ব্যবহারকারীরা সর্বোচ্চ ১০ MB সাইজের ছবি (JPEG, PNG, GIF, WebP) আপলোড করতে পারবেন।
- ভিউ (View): লিংক থাকলে যে কেউ ছবিটি দেখতে পারবেন — পাবলিক ছবি দেখার জন্য কোনো ধরনের লগ ইন বা অথেন্টিকেশনের দরকার নেই।
- ডিলিট (Delete): ছবির মালিকরা চাইলে তাদের আপলোড করা ছবি মুছে ফেলতে পারবেন।
- রিসাইজ বা থাম্বনেইল তৈরি (Resize/Thumbnail): বিভিন্ন জায়গায় (যেমন- প্রিভিউ, এমবেড বা গ্যালারি) ব্যবহার করার জন্য স্বয়ংক্রিয়ভাবে ছোট আকারের ছবি (যেমন- ১৫০×১৫০, ৩০০×৩০০, ৬০০×৬০০) তৈরি করতে হবে।
নন-ফাংশনাল রিকয়ারমেন্টস:
- লো ল্যাটেন্সি (Fast Serving): সারা বিশ্বের বেশিরভাগ ব্যবহারকারীর কাছে ছবিটি ৫০ মিলিসেকেন্ডের (ms) মধ্যে লোড হতে হবে। এ কাজের জন্য একটি CDN থাকা আবশ্যক।
- উচ্চ প্রাপ্যতা (High availability): সিস্টেমটিকে ৯৯.৯৯% সময় চালু থাকতে হবে। কোনো ছবির লিংক কাজ না করা বা ভাঙা থাকা একটি ভয়াবহ বাজে ইউজার এক্সপেরিয়েন্স।
- বড় ফাইল হ্যান্ডেল করা (Large files): ১০ MB পর্যন্ত বড় সাইজের ফাইল আপলোড করার সক্ষমতা থাকতে হবে। মাল্টিপার্ট আপলোড সামলানো এবং ধীরগতির কানেকশনের কারণে সিস্টেম টাইমআউট বা বন্ধ হওয়া চলবে না।
- স্থায়িত্ব (Durability): একবার আপলোড হওয়ার পর ছবি কখনোই হারিয়ে যাওয়া চলবে না। এর জন্য আমাদের ডাটা জমা রাখার একটি রিডান্ডেন্ট স্টোরেজ (redundant storage) বা বাড়তি মেমরি থাকতে হবে।
প্রাথমিক একটা হিসাব-নিকাশ
চলুন এবার সিস্টেমটির সাইজ হিসাব করি:
- প্রতিদিন ১০ মিলিয়ন ছবি আপলোড (সেকেন্ডে প্রায় ১১৫টি ছবি, আর পিক টাইমে প্রায় ৩৫০টি আপলোড/সেকেন্ড)।
- গড় ছবির সাইজ: ২ MB।
- রিড-রাইটের অনুপাত ১০:১: প্রতি সেকেন্ডে গড়ে প্রায় ১,১৫০টি ছবি দেখা হয়। পিক টাইমে, কিংবা কোনো ছবি ভাইরা্ল হলে, সেটি হতে পারে প্রায় ১.২ মিলিয়ন ভিউ/সেকেন্ড।
- দৈনিক স্টোরেজ বা জায়গা: ১০ মিলিয়ন × ২ MB = প্রতিদিন ২০ TB নতুন ছবি সেভ করার জায়গা প্রয়োজন।
- ৫ বছরের স্টোরেজ: ২০ TB × ৩৬৫ দিন × ৫ বছর = প্রায় ৩৬ PB (পেটাবাইট) (এটি শুধু আসল ছবির হিসাব—থাম্বনেইলের কারণে স্টোরেজ আরও প্রায় ৩০% বেড়ে যাবে)।
- ব্যান্ডউইথ: পিক টাইমে ১.২ মিলিয়ন রিডস/সেকেন্ড × গড়ে ২০০ KB সার্ভড সাইজ = ~২৪০ GB/সেকেন্ড আউটবাউন্ড (outbound) ডেটা — ঠিক এ কারণেই আমাদের একটি শক্তপোক্ত CDN দরকার।
এটি একটি স্টোরেজ-হেভি (স্টোরেজ-নির্ভর) এবং রিড-হেভি (বারবার দেখা হয় এমন) সিস্টেম। মূল চ্যালেঞ্জগুলো হলো—অল্প খরচে ছবি জমা রাখা, CDN-এর মাধ্যমে দ্রুত সার্ভ করা এবং ব্যাকগ্রাউন্ডে ছবি প্রসেসিং করার জন্য একটি অ্যাসিঙ্ক (async) পদ্ধতি কার্যকর করা।
API ডিজাইন
ছবি আপলোড করা
| Endpoint | POST /api/v1/images |
| Content-Type | multipart/form-data |
| Body | file (binary), title (optional), is_public (boolean) |
| Response | {"id": "img_abc123", "url": "https://cdn.imghost.com/abc123.jpg", "thumbnails": {...}} |
| Status | 201 Created |
ছবি দেখা
| Endpoint | GET /api/v1/images/:id |
| Query params | ?size=thumb|medium|large|original |
| Response | 302 redirect to CDN URL, or image binary |
ছবি ডিলিট করা
| Endpoint | DELETE /api/v1/images/:id |
| Auth | Bearer token (শুধুমাত্র মালিকের জন্য) |
| Response | 204 No Content |
ব্যবহারিক ক্ষেত্রে বা বাস্তবে সাধারণত GET /api/v1/images/:id API-টিতে হিট করার দরকার পড়ে না—ইউজাররা সরাসরি CDN-এর URL থেকেই ছবি পেয়ে যায়। এই API টি মূলত ছবি আপলোড করা, মেটাডেটা সেভ করা এবং মুছে ফেলার জন্য তৈরি করা হয়েছে।
ইমেজ প্রসেসিং পাইপলাইন (Image Processing Pipeline)
যখন কোনো ছবি আপলোড করা হয়, এটি শুধু ডেটাবেসে জমা হয় না—বরং একটি প্রসেসিং পাইপলাইনের মধ্যে দিয়ে যায়:
- যাচাই করা (Validation): ফাইলের ধরন, সাইজ (সর্বোচ্চ ১০ MB) এবং ডাইমেনশন (দৈর্ঘ্য-প্রস্থ) ঠিক আছে কিনা তা চেক করা হয়। সব ঠিক না থাকলে ফাইল বাতিল করা হয়।
- ডিডুপ্লিকেশন (Deduplication): ফাইলটির একটি কন্টেন্ট হ্যাশ (যেমন- SHA-256) তৈরি করা হয়। যদি সেই একই হ্যাশ আগে থেকেই সিস্টেমে সেভ করা থাকে, তবে নতুন করে ছবিটি স্টোর করার বদলে ওই আগের ছবিটিকেই রিটার্ন করা হয়। এতে করে স্টোরেজের ২০-৩০% জায়গা বাঁচানো যায়।
- থাম্বনেইল তৈরি (Thumbnail generation): ছবির বিভিন্ন রেজোলিউশনের কপি তৈরি করা হয়—যেমন, ১৫০×১৫০ (প্রোফাইল/প্রিভিউ), ৩০০×৩০০ (গ্যালারি), ৬০০×৬০০ (মাঝারি সাইজ)। এই কাজটি ব্যাকগ্রাউন্ডে একটি ওয়ার্কার কিউয়ের (Worker queue) মাধ্যমে অ্যাসিঙ্ক্রোনাসভাবে চলতে থাকে।
- ফাইল ফরম্যাট কনভার্সন (Format conversion): যেসব ব্রাউজার সাপোর্ট করে সেগুলোর জন্য ছবিকে WebP ফরম্যাটে রূপান্তর করা হয় (এটি সমমানের বা সেম কোয়ালিটির JPEG-এর চেয়ে প্রায় ৩০-৫০% ছোট জায়গা নেয়)। সিস্টেমটি সাধারণত দুটি ফরম্যাটের ছবিই আলাদা করে স্টোর করে রাখে।
- EXIF ডেটা বাদ দেওয়া (EXIF stripping): ইউজারের প্রাইভেসি নিশ্চিত করতে মূল ছবির সাথে থাকা মেটাডেটা (যেমন, লোকেশনের জিপিএস ডেটা, ক্যামেরার ডিটেইলস ইত্যাদি) স্থায়ীভাবে সরিয়ে ফেলা হয়। কেউ কখনো চাইবে না যে তার শেয়ার করা ছবিতে তার গোপন লোকেশন বা অন্য কোনো তথ্য সেভ করা থাকুক।
- কন্টেন্ট মডারেশন (Content moderation): কোনো অশালীন বা আপত্তিকর ছবি আছে কিনা তা চেক করতে একটি ML (Custom Machine Learning) মডেল অথবা থার্ড-পার্টি API ব্যবহার করা হয়। যদি কিছু পাওয়া যায়, তবে তা ব্লক বা রিজেক্ট করে দেওয়া হয়।
এখানে একটি বিষয় খুব জরুরি: শুধুমাত্র অরিজিনাল ছবিটি স্টোর করার কাজটি সিঙ্ক্রোনাসভাবে (synchronous) বা রিয়েল-টাইমে হয়। বাকি সব কাজ (যেমন- থাম্বনেইল তৈরি, ফরম্যাট কনভার্সন, মডারেশন) একটি মেসেজ কিউয়ের (message queue) মাধ্যমে অ্যাসিঙ্ক্রোনাসভাবে (background-এ) ঘটে। এর ফলে আপলোডে খুব সময় কম লাগে (প্রায় ২০০ মিলিসেকেন্ড)।
কীভাবে ছবি স্টোর ও ডাটাবেইসে সেভ করা হয় (Storage Strategy)
এই সিস্টেমে স্টোরেজ হলো সবচেয়ে বেশি খরচের এবং কঠিন অংশের একটি:
অবজেক্ট স্টোর (Amazon S3): সমস্ত আসল ছবি এবং থাম্বনেইল জমা রাখা হয়। S3-তে '11 nines' (৯৯.৯৯৯৯৯৯৯৯৯%) ডিউরেবিলিটি থাকে বা ডেটা নষ্ট হওয়া থেকে নিরাপদ থাকে। এখানে অটোমেটিক ব্যাকআপ নেওয়া হয়, এবং স্টোরেজ কখনো লিমিট পার করে না। কনটেন্ট হ্যাশ অনুসারে ডেটা সাজানো হয়, যেমন: s3://images/{hash_prefix}/{hash}.{ext}।
মেটাডেটা ডেটাবেস (Metadata Database): এখানে ছবির বিস্তারিত ডেটা বা মেটাডেটা স্টোর করা হয় — যেমন- ছবির আইডি, কার ছবি, কবে আপলোড করা হয়েছে, ছবির মাপ, কনটেন্ট হ্যাশ, থাম্বনেইলের ইউআরএল, কতবার দেখা হয়েছে ইত্যাদি। এসব ডেটা সাজানো অবস্থায় পাওয়ার জন্য রিলেশনাল ডেটাবেস (যেমন PostgreSQL) ব্যবহার করা ভালো, কারণ এতে ছবির স্ক্যান হিস্ট্রি বা তৈরি করার তারিখ সহজে ইনডেক্স করা যায়।
সিডিএন (CDN): ছবি ইউজারদের কাছে দেখানোর পুরো কাজটি একটি CDN (যেমন CloudFront, Fastly) এর মাধ্যমে করা হয়। এই CDN বিশ্বব্যাপী বিভিন্ন এজ-লোকেশন সার্ভারে ছবি ক্যাশ (cache) করে রাখে, যাতে ইউজাররা তাদের সবচেয়ে কাছের সার্ভার থেকে খুব দ্রুত ছবি পেয়ে যান। ছবি সাধারণত খুব একটা পরিবর্তন হয় না, তাই এর Cache TTL (রিমুভ হওয়ার সময়) ৩০ দিন রাখা যেতে পারে।
ডিডুপ্লিকেশন (Deduplication): কোনো ছবি স্টোর করার আগে সেটির কন্টেন্টের SHA-256 হ্যাশ বের করে নেওয়া হয়। এরপর মেটাডেটা ডেটাবেস চেক করা হয়—যদি সেই একই হ্যাশ আগে থেকেই থাকে, তবে নতুন রেকর্ডটিকে পুরনো S3 অবজেক্টটির সাথে লিংক করে দেওয়া হয়। এর ফলে, জনপ্রিয় কোনো মিম (meme) বা ছবি কয়েক হাজারবার আপলোড করা হলেও বারবার নতুন করে ডেটাবেসে স্টোর করতে হয় না। এতে বিপুল পরিমাণ জায়গা বেঁচে যায়।