ডাটাবেস শার্ডিং কীভাবে কাজ করে — এবং কেন এটি বোঝা কঠিন
শার্ডিং ডেটা একাধিক নোডে ভাগ করে ডাটাবেসের স্কেল বাড়ায়, কিন্তু এটি রাউটিং, রিব্যালান্সিং এবং নতুন ফল্ট মোড যোগ করে—যা সিস্টেমগুলোকে বোঝা কঠিন করে তোলে।

শার্ডিং কী (এবং কী নয়)
শার্ডিং (যাকে কখনও কখনও অনুভূমিক পার্টিশনিং বলা হয়) মানে আপনার অ্যাপের সামনে যা একটি একটি ডাটাবেস মনে হয়, সেটাকে একাধিক মেশিনে ভাগ করা—প্রতি মেশিনকে শার্ড বলা হয়। প্রতিটি শার্ড কেবল কিছু রো রাখে, কিন্তু মিলে পুরো ডেটাসেট প্রতিনিধিত্ব করে।
একটি লজিক্যাল টেবিল, অনেকটি ফিজিক্যাল জায়গা
একটি সহায়ক মানসিক মডেল হল লজিক্যাল স্ট্রাকচার বনাম ফিজিক্যাল প্লেসমেন্টের পার্থক্য।
- লজিক্যাল: আপনার কাছে এখনও একটি “Users” টেবিল আছে (একই কলাম, একই অর্থ)।
- ফিজিক্যাল: সেই টেবিলের রো বিভিন্ন জায়গায় স্টোর করা—উদাহরণস্বরূপ আইডি 1–1,000,000 শার্ড A-তে এবং পরের মিলিয়ন শার্ড B-তে।
অ্যাপের দৃষ্টিকোণ থেকে, আপনি কোয়েরি চালাতে চান যেন এটি একটি টেবিলই। কিন্তু আন্ডার দ্য হুড সিস্টেমকে সিদ্ধান্ত নিতে হবে কোন শার্ড(গুলি) সঙ্গে কথা বলবে।
কপি নয়, বড় নোড কেন-ও নয়
শার্ডিং রেপ্লিকেশন থেকে আলাদা। রেপ্লিকেশন একই ডেটার কপিকৌপী তৈরি করে একাধিক নোডে—মূলত উচ্চ প্রাপ্যতা এবং রিড স্কেলিং-এর জন্য। শার্ডিং ডেটা ভাগ করে যাতে প্রতিটি নোড বিভিন্ন রেকর্ড রাখে।
এটি ভার্টিকাল স্কেলিং থেকেও আলাদা, যেখানে আপনি একটি ডাটাবেস রাখেন কিন্তু সেটাকে বড় মেশিনে সরান (অধিক CPU/RAM/দ্রুত ডিস্ক)। ভার্টিকাল স্কেলিং সরল হতে পারে, কিন্তু বাস্তবে এতে সীমা থাকে এবং খরচ দ্রুত বাড়ে।
শার্ডিং যা জাদুকরি ভাবে ঠিক করে না
শার্ডিং ক্ষমতা বাড়ায়, কিন্তু এটি স্বয়ংক্রিয়ভাবে আপনার ডাটাবেসকে “সহজ” করে তুলবে না বা প্রতিটি কোয়েরি দ্রুত করবে না।
- জয়েন ব্যয়বহুল হতে পারে যদি সম্পর্কিত রো বিভিন্ন শার্ডে থাকে।
- ট্রাঞ্জেকশন শার্ডগুলোর ওপরে কঠিন; "সব-বা-কিছুই না" আপডেট করতে সমন্বয় দরকার।
- অপারেশনাল জটিলতা বেড়ে যায়: রাউটিং, রিব্যালান্সিং, ডিবাগিং এবং ফল্ট হ্যান্ডলিং সিস্টেমের অংশ হয়।
তাই শার্ডিংকে ভালভাবে বুঝতে হবে স্টোরেজ ও থ্রুপুট স্কেল করার উপায় হিসেবে—সবকিছুর বিনামূল্যে উন্নতি নয়।
টিমগুলো কেন শার্ড করে: সমাধান করার চেষ্টা করা সমস্যা
শার্ডিং সাধারণত প্রথম পছন্দ নয়। টিমগুলো সাধারণত সফল সিস্টেম ফিজিক্যাল সীমায় পৌঁছালে বা অপারেশনাল কষ্ট বাড়লে এটিকে বেছে নেয়। উদ্দীপনা কম “আমরা শার্ড করতে চাই” এবং বেশি “আমরা বৃদ্ধিহীনভাবে বাড়তে পারছি না”।
যেসব ব্যথার পয়েন্ট শার্ডিংয়ের দিকে ঠেলে দেয়
একটি সিঙ্গেল ডাটাবেস নোড বিভিন্নভাবে জায়গা হারাতে পারে:
- স্টোরেজ সীমা: টেবিল এবং ইনডেক্স বেড়ে ডিস্ক সংকুচিত হয়, ব্যাকআপ ধীর হয়, মেইনটেইন্যান্স বিপজ্জনক হয়।
- রাইট থ্রুপুট সীমা: CPU, WAL/রিডো, বা লক কনটেনশন কতটা লিখতে পারবেন তা সীমিত করে।
- রিড থ্রুপুট সীমা: কেশিং এবং রেপ্লিকা থাকলেও কিছু লোড প্রাইমারিকে অতিক্রম করে।
- নোইজি নেবর্স: একটি টেন্যান্ট বা কাস্টমারের প্যাটার্ন রিসোর্স দখল করে সবাইকে প্রভাবিত করে।
যখন এই সমস্যা নিয়মিত দেখা দেয়, প্রায়ই সমস্যাটা একটি খারাপ কোয়েরি নয়—একটি মেশিন খুব বেশি দায়বদ্ধতা বহন করছে।
লক্ষ্য: আউটস্কেল, আইসোলেট, এবং খরচ নিয়ন্ত্রণ করা
ডাটাবেস শার্ডিং ডেটা ও ট্রাফিক একাধিক নোডে ছড়ায় যাতে ক্যাপাসিটি বড় করে মেশিন যোগ করে—বড় মেশিন কেনার চেয়ে। ভালোভাবে করলে এটি ওয়ার্কলোড নিরোধও করতে পারে (এক টেন্যান্টের স্পাইক অন্যদের লেটেন্সি খারাপ করবে না) এবং খরচ নিয়ন্ত্রণে সাহায্য করে।
শুরুর চিহ্নগুলো যখন সীমায় পৌঁছার সংকেত দেয়
প্যাটার্নগুলো হল: পিক সময়ে p95/p99 ধীরে ধীরে বাড়া, রেপ্লিকেশন ল্যাগ দীর্ঘ হওয়া, ব্যাকআপ/রিস্টোর আপনার গ্রহণযোগ্য উইন্ডো ছাড়িয়ে যাওয়া, এবং ছোট স্কিমা পরিবর্তন বড় ইভেন্টে পরিণত হওয়া।
কেন শার্ডিং সাধারণত শেষ ধাপ
শুরু করার আগে টিমগুলো সাধারণত সহজ অপশনগুলো শেষ করে: ইনডেক্সিং ও কোয়েরি ফিক্স, কেশিং, রিড রেপ্লিকা, এক নোডে পার্টিশনিং, পুরনো ডেটা আর্কাইভ করা, এবং হার্ডওয়্যার আপগ্রেড। শার্ডিং স্কেল সমাধান করে, কিন্তু সঙ্গে নিয়ে আসে সমন্বয়, অপারেশনাল জটিলতা, এবং নতুন ফল্ট মোড—তাই কদাচিত সিদ্ধান্ত নেয়া উচিত।
মূল উপাদানগুলো: শার্ড, রাউটার এবং মেটাডেটা
একটি শার্ডেড ডাটাবেস একটিই বস্তু নয়—এটি কয়েকটি সমন্বিত অংশের সিস্টেম। শার্ডিংকে “বুঝতে কঠিন” মনে হওয়ার কারণ হল সঠিকতা এবং পারফরম্যান্স এই অংশগুলোর পারস্পরিক ক্রিয়ার উপর নির্ভর করে, কেবল ডাটাবেস ইঞ্জিনের উপর নয়।
শার্ডস: স্বতন্ত্র পার্টিশন (নিজেদের ইনডেক্সসহ)
একটি শার্ড হলো ডেটার একটি উপসেট, সাধারণত আলাদা সার্ভার বা ক্লাস্টারে স্টোর করা। প্রতিটি শার্ড সাধারণত রাখে:
- স্টোরেজ (ডেটা ফাইল)
- ইনডেক্স (তাই ওই শার্ডের ভিতরে কোয়েরি দ্রুত হবে)
- লোকাল সীমা (CPU, মেমরি, ডিস্ক, কানেকশন)
অ্যাপ থেকে দেখা গেলে, শার্ডেড সেটআপ প্রায়ই একটি লজিক্যাল ডাটাবেসের মতো দেখতে চায়। কিন্তু আন্ডার দ্য হুড, একটি লুকআপ যা একটাই ইনডেক্স লুকআপ হলে তা হয়ে যেতে পারে “সঠিক শার্ড খুঁজে তারপর লুকআপ করা”।
রাউটার/কোঅর্ডিনেটর: অনুরোধ কিভাবে সঠিক শার্ডে পৌঁছে
একটি রাউটার (কোঅর্ডিনেটর, কোয়েরি রাউটার বা প্রক্সি বলা হয়) ট্র্যাফিকের পুলিশ। এটি বাস্তবত প্রশ্নের উত্তর দেয়: এটি অনুরোধ দিলে কোন শার্ডটি তা হ্যান্ডেল করবে?
দুই সাধারণ প্যাটার্ন আছে:
- ক্লায়েন্ট-সাইড রাউটিং: আপনার অ্যাপ লাইব্রেরি শার্ড ম্যাপ জানে এবং সরাসরি সঠিক শার্ডে কানেক্ট করে।
- প্রক্সি রাউটিং: অ্যাপ একটি রাউটার সার্ভিসে কানেক্ট করে, যা অনুরোধ ফরওয়ার্ড করে।
রাউটার অ্যাপের জটিলতা কমায়, কিন্তু সঠিকভাবে ডিজাইন না করলে তারা বটলনেক বা নতুন একটি ফল্ট পয়েন্টও হতে পারে।
মেটাডেটা/কনফিগ সার্ভিস: শার্ড ম্যাপ, মালিকানা, এবং হেলথ
শার্ডিং মেটাডেটার উপর নির্ভর করে—একটি ট্রুথ সোর্স যা বর্ণনা করে:
- শার্ড ম্যাপ (কোন শার্ড কোন রেঞ্জ/হ্যাশ বকেট/আইডি মালিক)
- মালিকানা (বিশেষত মাইগ্রেশনের সময়, যখন মালিকানা অভিন্ন হতে পারে)
- হেলথ ও মেমবারশিপ (কোন নোড আপ, প্রাইমারি/রেপ্লিকা রোলস, ড্রেইনিং স্ট্যাটাস)
এই তথ্য প্রায়ই একটি কনফিগ সার্ভিসে থাকে। যদি মেটাডেটা স্টেইল বা অসামঞ্জস্যপূর্ণ হয়, রাউটার ভুল শার্ডে ট্রাফিক পাঠাতে পারে—শার্ডগুলো ঠিক থাকলেও।
ব্যাকগ্রাউন্ড জবস: ব্যালেন্সিং, মাইগ্রেশন, এবং ব্যাকআপ
শেষে, শার্ডিং নির্ভর করে ব্যাকগ্রাউন্ড প্রসেসগুলোর উপর যা সিস্টেমকে সময়ের সাথে ব্যবহার উপযোগী রাখে:
- রিব্যালান্সিং যখন একটি শার্ড অন্যগুলোর থেকে দ্রুত বাড়ে
- মাইগ্রেশন যখন মালিকানা শার্ডের মধ্যে সরানো হয়
- ব্যাকআপ/রিস্টোর পদ্ধতি যা অনেক শার্ড জুড়ে কাজ করে এবং আপনার RTO/RPO-কে মেনে চলে
এসব জব শুরুতে উপেক্ষা করা সহজ, কিন্তু প্রোডাকশনে বিস্ময় সাধনের কারণ হয়ে থাকে—কারণ এগুলো সিস্টেমের আকৃতি বদলে দেয় সার্ভিস চলাকালে।
শার্ড কী নির্বাচন: প্রথম বড় ট্রেড-অফ
শার্ড কী হল সেই ক্ষেত্র (বা ক্ষেত্রগুলোর কম্বিনেশন) যা ব্যবহার করে সিস্টেম সিদ্ধান্ত নেয় কোন শার্ডে একটি রো/ডকুমেন্ট রাখবে। একটিই সিদ্ধান্ত নীরবে আপনার পারফরম্যান্স, খরচ, এবং ভবিষ্যতের বৈশিষ্ট্য সহজ বা কঠিন করে দেয়—কারণ এটি নির্ধারণ করে অনুরোধটি এক শার্ডে যেতে পারে কি না বা অনেক শার্ডে ফ্যান-আউট হবে কি না।
ভাল শার্ড কী কী গুণ রাখে
ভাল কী সাধারণত থাকে:
- উচ্চ কার্ডিনালিটি: অনেক সম্ভাব্য মান (যেমন
user_idvs country) - সমান বণ্টন: ভ্যালুগুলো শার্ডগুলোর মধ্যে পড়াশোনা করে লিখা ও পড়া সমানভাবে ছড়ায়
- স্থিতিশীল অ্যাক্সেস প্যাটার্ন: এটি এমনভাবে ম্যাচ করে যেভাবে আপনি আজ অভিগমন করেন এবং আপনি পরের ক্বার্টারে কিভাবে আশা করেন
একটি সাধারণ উদাহরণ হল tenant_id দিয়ে শার্ডিং: অধিকাংশ ওই টেন্যান্টের পড়া/লিখা এক শার্ডেই থাকে এবং টেন্যান্টগুলো প্রচুর হলে লোড ছড়ায়।
খারাপ কী কি করে (এবং কেন ব্যথা দেয়)
কিছু কী প্রায়ই কষ্টের নিশ্চয়তা দেয়:
- টাইম-ভিত্তিক মোনোটোনিক কী (টাইমস্ট্যাম্প, অটো-ইনক্রিমেন্ট আইডি): নতুন ডেটা সর্বদা "সর্বশেষ" শার্ডে জমে লিখ হটস্পট তৈরি করে
- কম কার্ডিনালিটি ফিল্ড (স্ট্যাটাস, প্ল্যান টিয়ার, দেশ): কম ভিন্ন মান → কয়েকটি শার্ডই কাজের বেশিরভাগ করে
- পরিবর্তনশীল আইডেন্টিফায়ার (ইমেইল, পরিবর্তনশীল ইউজারনেম): কী বদলালে ডেটা শার্ড বদলাতে খরচ ও ঝুঁকি বাড়ে
এমনকি যদি কোন কম-কার্ডিনালিটি কী ফিল্টারিং সুবিধা দেয়, তা প্রায়ই রুটিন কোয়েরিগুলোকে স্ক্যাটার-গ্যাদার করে দেয় কারণ ম্যাচিং রো সব জায়গায় থাকে।
প্রকৃত ট্রেড-অফ: কোয়েরি সুবিধা বনাম বণ্টনের গুণ
লোড ব্যালান্সিং-এর জন্য সেরা শার্ড কী সবসময় প্রোডাক্ট কোয়েরিগুলোর জন্য সেরা নয়।
- একটি কী বেছে নিন যা আপনার প্রধান অ্যাক্সেস প্যাটার্নের সাথে মিল রেখে (যেমন
user_id), এবং কিছু "গ্লোবাল" কোয়েরি (অ্যাডমিন রিপোর্টিং) ধীর হবে বা আলাদা পাইপলাইন দরকার হবে। - একটি কী যদি রিপোর্টিং-উদ্দেশ্যে নেওয়া হয় (যেমন
region) আপনি হটস্পট ও অসম ক্ষমতার ঝুঁকি নেবেন।
অধিকাংশ টিম এই ট্রেড-অফ অনুযায়ী ডিজাইন করে: শার্ড কী অপটিমাইজ করে সবচেয়ে বেশি, ল্যাটেন্সি সংবেদনশীল অপারেশনগুলোর জন্য—বাকি কাজগুলোকে ইনডেক্স, ডেনর্মালাইজেশন, রেপ্লিকা, বা ডেডিকেটেড অ্যানালিটিক্স টেবিল দিয়ে হ্যান্ডেল করা হয়।
প্রচলিত শার্ডিং কৌশল (রেঞ্জ, হ্যাশ, ডিরেক্টরি)
একটি "সেরা" উপায় নেই। আপনি যে কৌশল নেন তা রাউটিং কেমন হবে, ডেটা কিভাবে ছড়াবে, এবং কোন অ্যাক্সেস প্যাটার্নগুলো ব্যথা দেবে তা নির্ধারণ করে।
রেঞ্জ শার্ডিং
রেঞ্জ শার্ডিং-এ প্রতিটি শার্ড কী স্পেসের ধারাবাহিক একটি স্লাইস দিয়ে মালিকানা করে—for example:
- শার্ড A: customer_id 1–1,000,000
- শার্ড B: customer_id 1,000,001–2,000,000
রাউটিং সরল: কী দেখে শার্ড বেছে নিন।
কিন্তু সমস্যা হল হটস্পট। যদি নতুন ইউজারদের আইডি ক্রমাগত বাড়ে, "শেষ" শার্ড লেখার বটলনেক হয়ে যায়। রেঞ্জ শার্ডিং অসম বৃদ্ধি/পপুলারিটির প্রতি সংবেদনশীল। সুবিধা: রেঞ্জ কোয়েরি ("অক্টোবর 1–31-এর সব অর্ডার") দক্ষ হতে পারে কারণ ডেটা শারীরিকভাবে গ্রুপ করা থাকে।
হ্যাশ শার্ডিং
হ্যাশ শার্ডিং-এ শার্ড কী-কে একটি হ্যাশ ফাংশনের মধ্য দিয়ে পাঠিয়ে শার্ড বেছে করা হয়। এটি সাধারণত ডেটা সমানভাবে ছড়ায়, ফলে "নতুন সবকিছু সর্বশেষ শার্ডে" সমস্যা কমে।
ট্রেড-অফ: রেঞ্জ কোয়েরি কষ্টকর। X থেকে Y আইডি পর্যন্ত কাস্টমারদের খুঁজে পেতে বহু শার্ডে ছোড়া লাগতে পারে।
একটা বাস্তবিক বিবরণ যে টিমগুলো প্রায়ই অবমূল্যায়ন করে সেটা হল কনসিস্টেন্ট হ্যাশিং। সরাসরি শার্ড কাউন্টে ম্যাপ করলে নতুন শার্ড যোগ করলে সব কিছু রিশাফল হয়ে যায়; অনেক সিস্টেম হ্যাশ রিং ও ভার্চুয়াল নোড ব্যবহার করে যখন নতুন ক্যাপাসিটি যোগ করলে কেবল কিছু কী সরান।
ডিরেক্টরি (লুকআপ) শার্ডিং
ডিরেক্টরি শার্ডিং-এ একটি স্পষ্ট ম্যাপ থাকে কী → শার্ড লোকেশন। এটি সবচেয়ে নমনীয়: নির্দিষ্ট টেন্যান্টকে ডেডিকেটেড শার্ডে রাখা যায়, একটি কাস্টমারকে একাই সরানো যায়, এবং অসম শার্ড সাইজ সাপোর্ট করা যায়।
কিন্ত্য অসুবিধা হল এক অতিরিক্ত নির্ভরতা। যদি ডিরেক্টরি ধীর, স্টেইল, বা অপ্রাপ্য হয়, রাউটিং ক্ষতিগ্রস্ত হয়—even যদি শার্ডগুলো সুস্থও থাকে।
কম্পোজিট কী এবং সাব-শার্ডিং
বাস্তব সিস্টেম প্রায়ই পদ্ধতিগুলো মিশ্রিত করে। একটি কম্পোজিট কী (যেমন tenant_id + user_id) টেন্যান্টকে আইসোলেট রাখে আর একই টেন্যান্টের ভেতরে লোড ছড়ায়। সাব-শার্ডিং অনুরূপ: প্রথমে টেন্যান্ট অনুযায়ী রাউট করুন, তারপর ঐ টেন্যান্টের শার্ড গ্রুপের মধ্যে হ্যাশ করে একটি শার্ড চয়ন করুন যাতে বড় টেন্যান্ট এক শার্ড দখল না করে।
কোয়েরি কিভাবে চলে: রাউটিং বনাম স্ক্যাটার-গ্যাদার
একটি শার্ডেড ডাটাবেসের দুটি ভিন্ন "কোয়েরি পথ" আছে। কোন পথ আপনি পাচ্ছেন তা বুঝলে পারফরম্যান্সের অনেক বিস্ময় ব্যাখ্যা করা যায়—এবং কেন শার্ডিং অনিশ্চিত মনে হতে পারে।
সিঙ্গেল-শার্ড কোয়েরি: দ্রুত পথ
আইডিয়াল হল কোয়েরি ঠিক এক শার্ডে রাউট করা। যদি অনুরোধে শার্ড কী থাকে (অথবা রাউটার সেটিকে শার্ড-তে ম্যাপ করতে পারে), সিস্টেম সরাসরি সেখানেই পাঠাতে পারে।
এই কারণে টিমগুলো প্রচলিত রিডগুলোকে "শার্ড-কী সচেতন" করার চেষ্টা করে। এক শার্ড মানে কম নেটওয়ার্ক হপ, সহজ এক্সিকিউশন, কম লক, এবং কম সমন্বয়—লেটেন্সি প্রধানত ডাটাবেস কাজ করছে বলে থাকে, ক্লাস্টার আলোচনা নয়।
স্ক্যাটার-গ্যাদার রিড: ফ্যান-আউট এবং টেইল ল্যাটেন্সি
যখন কোয়েরি সঠিকভাবে রাউট করা যায় না (উদাহরণ: নন-শার্ড-কী ফিল্ডে ফিল্টার করে), সিস্টেম অনেক বা সব শার্ডে ব্রডকাস্ট করতে পারে। প্রতিটি শার্ড স্থানীয়ভাবে কোয়েরি চালায়, পরে রাউটার ফলাফল মেলায়—সোর্টিং, ডুপ্লিকেট রিমুভ, লিমিট প্রয়োগ, এবং পারশিয়াল অ্যাগ্রিগেট সমন্বয় করে।
এই ফ্যান-আউট টেইল ল্যাটেন্সি বাড়ায়: 9টি শার্ড দ্রুত সাড়া দিলেও একটি ধীর শার্ড পুরো অনুরোধকে আটকে দিতে পারে। এছাড়া লোড গুণিতক হয়: এক ইউজার অনুরোধ N শার্ড অনুরোধে পরিণত হয়।
ক্রস-শার্ড জয়েন ও অ্যাগ্রিগেশন
শার্ডগুলোর ওপর জয়েন ব্যয়বহুল কারণ ডেটা যা এক ডাটাবেসে ভেতরেই মিলত, এখন শার্ডগুলোর মধ্যে যেতে বা একটি কোঅর্ডিনেটরে যেতে হয়। এমনকি সাধারণ অ্যাগ্রিগেশনও দুই-ফেজ প্ল্যান চাইতে পারে: প্রতিটি শার্ডে পারশিয়াল ফলাফল কম্পিউট করে পরে মের্জ করা।
ইনডেক্সিং সীমাবদ্ধতা: লোকাল বনাম গ্লোবাল
অধিকাংশ সিস্টেম ডিফল্টভাবে লোকাল ইনডেক্স ব্যবহার করে: প্রতিটি শার্ড কেবল তার নিজের ডেটা ইনডেক্স করে। এগুলো রক্ষণাবেক্ষণে সস্তা, কিন্তু রাউটিংয়ে সাহায্য করে না—তাই কোয়েরি এখনও ছড়াতে পারে।
গ্লোবাল ইনডেক্স অ-শার্ড-কী ফিল্ডে টার্গেটেড রাউটিং সক্ষম করতে পারে, কিন্তু এগুলো লিখনে ওভারহেড, অতিরিক্ত সমন্বয়, এবং নিজস্ব স্কেলিং ও কনসিস্টেন্সি চ্যালেঞ্জ যোগ করে।
লেখাপড়া এবং শার্ডগুলোর ওপরে ট্রাঞ্জেকশন
লিখা যেখানে শার্ডিং "কেবল স্কেল" থেকে বাস্তবে পরিবর্তিত হয় এবং ফিচার ডিজাইন বদলে দেয়। একটি লেখা যদি এক শার্ডকে টাচ করে তবে দ্রুত ও সহজ। কিন্তু একটি লেখা যদি একাধিক শার্ডে লাগে, তখন ধীর, ব্যর্থপ্রবণ এবং সঠিকভাবে করা কঠিন হয়ে যায়।
এক-শার্ড লেখাঃ খুশির পথ
যদি প্রতিটি অনুরোধ সঠিকভাবে একটি শার্ডে রাউট করা যায় (সাধারণত শার্ড কী-র মাধ্যমে), ডাটাবেস তার স্বাভাবিক ট্রাঞ্জেকশন মেশিনারি ব্যবহার করতে পারে। শার্ড-অন্তর্গত অ্যাটমিকিটি ও আইসোলেশন পাওয়া যায়, এবং অপারেশনাল ইস্যুগুলো পরিচিত single-node সমস্যার মতোই দেখা দেয়—শুধু N বার।
বহু-শার্ড লেখাঃ যেখানে জটিলতা বাড়ে
যখন একটি লজিক্যাল অ্যাকশনে দুটি শার্ডে ডেটা আপডেটের প্রয়োজন হয় (উদাহরণ: টাকা ট্রান্সফার, অর্ডার এক কাস্টমার থেকে আর এক কাস্টমারে সরানো, বা কোথাও সংরক্ষিত অ্যাগ্রিগেট আপডেট করা), তখন আপনি ডিস্ট্রিবিউটেড ট্রাঞ্জেকশনে প্রবেশ করেন।
ডিস্ট্রিবিউটেড ট্রাঞ্জেকশন কঠিন কারণ বিভিন্ন মেশিনের মধ্যে সমন্বয় দরকার—যেগুলো ধীর, পার্টিশন্ড, বা রিস্টার্ট হতে পারে। দুই-ফেজ কমিট স্টাইল প্রটোকল অতিরিক্ত রাউন্ড-ট্রিপ যোগ করে, টাইমআউটে ব্লক করতে পারে, এবং ব্যর্থতাকে অনিশ্চিত করে: শার্ড B কি পরিবর্তনটি অ্যাপ্লাই করেছে আগে কোঅর্ডিনেটর ডাই করছে? ক্লায়েন্ট রিট্রাই করলে ডাবল-অ্যাপ্লাই হবে কি? যদি রিট্রাই না করা হয়, কি হারাবে?
ক্রস-শার্ড লেখার এড়ানোর প্যাটার্ন
কিছু প্রচলিত কৌশল ক্রস-শার্ড ট্রাঞ্জেকশনের প্রয়োজন কমায়:
- ডেটা লোকালিটি: সম্পর্কিত রেকর্ডগুলো একই শার্ডে একত্রিত রাখা (উদাহরণ: একটি কাস্টমারের সবকিছু)
- রিকুয়েস্ট রাউটিং: একটি অপারেশনকে এক শার্ডের মালিকানায় রাখা এবং অন্য শার্ডগুলোকে রিড-ওনলি হিসেবে বিবেচনা করা
- ডেনর্মালাইজেশন: ছোট ডেটার পিসগুলো নকল করে আপডেট ফ্যান-আউট প্রয়োজন কমানো
আইডেমপটেন্সি এবং রিট্রাই সেফটি
শার্ডেড সিস্টেমে রিট্রাই অনিবার্য—তাই লেখাগুলোকে আইডেমপটেন্ট করা জরুরি: স্থির অপারেশন আইডি (উদাহরণ: idempotency key) ব্যবহার করা এবং ডাটাবেসে “আগে করা হয়েছে” মার্কার রাখা। এতে টাইমআউট হলে ক্লায়েন্ট রিট্রাই করলে দ্বিতীয় প্রচেষ্টা নো-অপ হবে, ডাবল চার্জ বা অনিয়মিত কাউন্টার হবে না।
কনসিস্টেন্সি এবং রেপ্লিকেশন: ডেটা সঠিক রাখা
শার্ডিং ডেটা মেশিনে ভাগ করে—তবে এটি redundancy-র প্রয়োজন দূর করে না। রেপ্লিকেশন একটি শার্ডকে তখনও উপলব্ধ করে যখন একটি নোড পড়ে যায়—এবং এটি সেই প্রশ্নটাকে কঠিন করে তোলে: "এখন কি সত্য?"
প্রতিটি শার্ডের ভিতরে রেপ্লিকেশন
অধিকাংশ সিস্টেম প্রতিটি শার্ডের ভিতরেই রেপ্লিকেশন করে: একটি প্রাইমারি (লিডার) লিখা গ্রহণ করে এবং এক বা একাধিক রেপ্লিকা কপি করে। যদি প্রাইমারি ব্যর্থ হয়, সিস্টেম একটি রেপ্লিকা প্রোমোট করে (ফেইলোওভার)। রেপ্লিকা পড়া সার্ভ করতে পারে লোড কমাতে।
ট্রেড-অফ হল টাইমিং। একটি রিড রেপ্লিকা মিলিসেকেন্ড বা সেকেন্ড পিছিয়ে থাকতে পারে। সেই গ্যাপ স্বাভাবিক, কিন্তু যাদের প্রত্যাশা আছে "আমি ঠিক এখনই আপডেট করেছি, তাই আমি তা দেখতে পাব"—তার ক্ষেত্রে এটা সমস্যা।
কনসিস্টেন্সি মডেল সরলভাবে
- স্ট্রং কনসিস্টেন্সি: লেখা সফল হলে পড়া সেটিকে প্রতিফলিত করবে (সিস্টেম যা গ্যারান্টি দেয় সেই দৃষ্টিকোণ থেকে)। সাধারণত এটি লিডার থেকে পড়া বা রেপ্লিকার কনফার্মেশন অপেক্ষা করার মাধ্যমে হয়।
- ইভেন্টুয়াল কনসিস্টেন্সি: সিস্টেম মিলিয়ে নেবে, কিন্তু একটি পড়া সাময়িকভাবে পুরোনো ডেটা ফিরিয়ে দিতে পারে।
শার্ডিং-এ প্রায়ই আপনি দেখতে পাবেন একটি শার্ডের ভেতরে শক্তিশালী কনসিস্টেন্সি এবং শার্ডগুলোর মধ্যে দুর্বল গ্যারান্টি, বিশেষত যখন ক্রস-শার্ড অপারেশন থাকে।
বিভক্ত ডেটায় “সিঙ্গল সোর্স অফ ট্রুথ”
শার্ডিং-এর সাথে, “সিঙ্গল সোর্স অফ ট্রুথ” সাধারণত মানে: প্রতিটি ডাটা টুকরোর জন্য একটি কর্তৃত্বপূর্ণ লিখন জায়গা আছে (সাধারণত শার্ডের লিডার)। কিন্তু গ্লোবালি সমস্ত কিছুর সর্বশেষ স্টেট দ্রুত प्रमाणন করে এমন একটি মেশিন নেই। আপনার কাছে অনেক লোকাল ট্রুথ থাকে যেগুলোকে রেপ্লিকেশনের মাধ্যমে সিঙ্ক রাখা হয়।
গ্লোবাল কনস্ট্রেইন্ট: ইউনিকনেস, ফরেন কি, কাউন্টার
কনস্ট্রেইন্টগুলো জটিল যখন যে ডেটা চেক করা দরকার তা বিভিন্ন শার্ডে থাকে:
- ইউনিকনেস (উদাহরণ: ইউজারনেম): "সব জায়গায় ডুপ্লিকেট নেই" জোরদার করতে কেন্দ্রীভূত ইনডেক্স, ডেডিকেটেড কনস্ট্রেইন্ট শার্ড, বা অ্যাপ-লেভেল রিজার্ভেশন ওয়ার্কফ্লো লাগতে পারে।
- ফরেন কি: প্যারেন্ট ও চাইল্ড রো বিভিন্ন শার্ডে থাকলে রেফারেনশিয়াল ইন্টিগ্রিটি সহজে এঞ্জোর করা যায় না ছাড়া ক্রস-শার্ড সমন্বয়ের।
- কাউন্টার (গ্লোবাল টোটাল, সিকুয়েন্সিয়াল আইডি): সরল পদ্ধতি বটলনেক তৈরি করে; পপুলার ফিক্স হলো প্রতিটি শার্ডকে রেঞ্জ দেয়া, ব্যাচিং, বা আনুমানিক কাউন্ট গ্রহণ করা।
এই পছন্দগুলো কেবল ইমপ্লিমেন্টেশন নয়—এগুলো ঠিক করে দেয় আপনার প্রোডাক্টের জন্য কি "সঠিক"।
রিব্যালান্সিং ও রিশার্ডিং ডাউনটাইম ছাড়া
রিব্যালান্সিংই একটি শার্ডেড ডাটাবেসকে বাস্তবিক উপযোগী রাখে সময়ের সাথে। ডেটা অসমভাবে বাড়ে, একটি শার্ড কি-তে স্কিউ আসে, আপনি নতুন নোড যোগ করেন, বা হার্ডওয়্যার অবসর নেওয়া দরকার—এসব কিছুই এক শার্ডকে বোতলনেক বানিয়ে দিতে পারে—যদিও প্রাথমিক ডিজাইন পারফেক্ট ছিল।
কেন এটা কঠিন
একটি একক ডাটাবেসের তুলনায়, শার্ডিং ডেটার অবস্থান রাউটিং লজিকের মধ্যে বেকড ইন করে দেয়। যখন আপনি ডেটা সরান, আপনি কেবল বাইট কপি করছেন না—আপনি বদলে দিচ্ছেন কই থেকে কোয়েরি আসবে। তাই রিব্যালান্সিং মেটাডেটা ও ক্লায়েন্টের ব্যাপার নিয়ে জটিল।
অনলাইন মাইগ্রেশন প্যাটার্ন (কপি → ওভারল্যাপ → কাটওভার)
অধিকাংশ টিম অনলাইন ওয়ার্কফ্লো লক্ষ্য করে যাতে বড় ডাউনটাইম না লাগে:
- কপি: সোর্স শার্ড থেকে টার্গেটে ব্যাকফিল করুন সার্ভিং চলাকালীন
- ডুয়াল-রাইট (কিন্তু মাঝে মাঝে ডুয়াল-রিড): ট্রানজিশনে নতুন পরিবর্তন উভয় লোকেশনেই লিখুন
- কাটওভার: শার্ড ম্যাপ পরিবর্তন করে রাউটার/ক্লায়েন্টকে নতুন লোকেশনে পাঠান
- ক্লিনআপ: ডুয়াল-রাইট বন্ধ করে পুরাতন কপি মুছে দিন এবং স্পেস রিক্লেইম করুন
শার্ড ম্যাপ ও ক্লায়েন্ট আচরণ
শার্ড ম্যাপ বদলানো ব্রেকিং ইভেন্ট হতে পারে যদি ক্লায়েন্ট রাউটিং ডিসিশন ক্যাশ করে রাখে। ভাল সিস্টেম রাউটিং মেটাডেটাকে কনফিগের মত বিবেচনা করে: ভার্সনিং করে, প্রায়ই রিফ্রেশ করে, এবং স্পষ্টভাবে নির্ধারণ করে কী ঘটবে যখন ক্লায়েন্ট একটি মুভ করা কী-তে আচরণ করবে (রিডাইরেক্ট, রিট্রাই, বা প্রোক্সি)।
অপারেশনাল ঝুঁকি পরিকল্পনা করা
রিব্যালান্সিং অস্থায়ী পারফরম্যান্স ডাব্লিউপ চালাতে পারে (অতিরিক্ত লিখা, ক্যাশ চার্ন, ব্যাকগ্রাউন্ড কপি লোড)। আংশিক মুভ সাধারন—কিছু রেঞ্জ আগে মাইগ্রেট হয়—তাই পর্যবেক্ষণ ও রোলব্যাক পরিকল্পনা থাকা উচিত (উদাহরণ: ম্যাপ ফিরিয়ে দেওয়া এবং ডুয়াল-রাইট ড্রেইন করা) কাটওভার শুরু করার আগে।
হটস্পট ও স্কিউ: যখন “সমান ভাগ” ভাঙে
শার্ডিং ধরে নেয় কাজ ছড়াবে। আশ্চর্যজনক বিষয় হল ক্লাস্টার কাগজে “সমান” দেখলেও প্রোডাকশনে অত্যন্ত অসম আচরণ করতে পারে।
হট পার্টিশন (হট কী)
হটস্পট ঘটে যখন কী-স্পেসের একটি ছোট অংশ ট্রাফিকের বেশিরভাগ টানতে শুরু করে—একটি সেলিব্রিটি অ্যাকাউন্ট, জনপ্রিয় প্রোডাক্ট, একটি টেন্যান্টের ভারি ব্যাচ জব, বা টাইম-ভিত্তিক কী যেখানে "আজ" সব লেখাকে আকর্ষণ করে। যদি সেই কী-গুলো একটি শার্ডে পড়ে, সেই শার্ড বোতলনেক হয়ে যায় যদিও অন্য শার্ডগুলো অলস থাকে।
স্কিউ: ডেটা সাইজ বনাম ট্রাফিক
“স্কিউ” এক নয়:
- ডেটা স্কিউ: একটি শার্ডে বেশি বাইট/রো থাকে (স্টোরেজ প্রেসার, দীর্ঘ ব্যাকআপ)
- ট্রাফিক স্কিউ: একটি শার্ড বেশি QPS বা ভারি কোয়েরি দেখে (CPU স্যাচুরেশন, লেটেন্সি স্পাইক)
এগুলো মিলবে না-ও পারে: কম ডেটা থাকা শার্ডটিই সবচেয়ে হট হতে পারে যদি সেটি সবচেয়ে অনুরোধপ্রাপ্ত কীগুলো রাখে।
দ্রুত সনাক্তকরণ কিভাবে করবেন
আপনি জটিল ট্রেসিং ছাড়াই স্কিউ দেখতে পাবেন। প্রতি-শার্ড ড্যাশবোর্ড থেকে শুরু করুন:
- প্রতিটি শার্ডের p95 latency (এক শার্ডের p95 উঠলে সতর্কতা)
- প্রতিটি শার্ডের QPS (ও লিখা QPS)
- প্রতি-শার্ড স্টোরেজ/টেবিল সাইজ
যদি একটি শার্ডের লেটেন্সি তার QPS বাড়ার সাথে বৃদ্ধি পায় আর অন্যগুলো সমতল থাকে, আপনি সম্ভবত একটি হটস্পটে আছেন।
শমেন্টস
ফিক্সগুলো সাধারণত সরলতা বনাম ভারসাম্যের মধ্যে ট্রেড-অফ:
- এমন শার্ড কী বেছে নিন যা ট্রাফিক ছড়ায়, কেবল রেকর্ড নয়
- হট কী-গুলোর জন্য বকেটিং/সাল্টিং যোগ করুন (একটি লজিক্যাল কীকে একাধিক ফিজিক্যাল বকেটে ভাগ করা)
- রিড-হেভি আইটেমগুলোর জন্য ক্যাশিং ব্যবহার করুন
- রিসোর্স রক্ষার জন্য রেট-লিমিট বা টেন্যান্ট কোটা প্রয়োগ করুন
- হট শার্ড স্প্লিট বা হট রেঞ্জগুলিকে সরান যখন একটি শার্ড ঠাণ্ডা করা সম্ভব না
শার্ডেড সিস্টেমে ফল্ট মোড এবং ডিবাগিং
শার্ডিং শুধুমাত্র সার্ভার বাড়ায় না—এটি আরও অনেক ভুলের পথ যোগ করে, এবং খুঁজে বের করার জন্য আরও জায়গা রাখে। অনেক ইনসিডেন্ট হয় "ডাটাবেস ডাউন" না বলেই, বরং "একটি শার্ড ডাউন" বা "সিস্টেম ঠিক কোথায় ডেটা আছে সে নিয়ে একমত নয়"।
প্রচলিত ফল্ট মোড
কিছু প্যাটার্ন বারবার দেখা যায়:
- একটি শার্ড অনুপলব্ধ (ক্র্যাশ, ডিস্ক ফুল, দীর্ঘ GC) → আংশিক আউটেজ: কিছু গ্রাহক কাজ করে, অন্যরা ব্যর্থ
- রাউটার ভুল রাউট করে, প্রায়ই কনফিগ চেঞ্জ বা খারাপ ডেপ্লয়ের পরে; রিডগুলি ভুল শার্ডে গেলে নীরবে খালি ফলাফল দিতে পারে
- স্টেইল বা অসামঞ্জস্যপূর্ণ মেটাডেটা (উদাহরণ: শার্ড ম্যাপ) → মাইগ্রেশন বা স্প্লিট চলাকালে বিভিন্ন কম্পোনেন্ট একই কী-কে ভিন্নভাবে রাউট করতে পারে
- পার্শিয়াল নেটওয়ার্ক ইস্যু: রাউটার ও কিছু শার্ডের মধ্যে টাইমআউট র্যান্ডম এরর মনে হয় এবং রিট্রাই লোড বাড়ায়
ডিবাগিং কিভাবে বদলে যায়
একটি সিঙ্গেল-নোড ডাটাবেসে আপনি একটা লোগ টেইল করেন এবং মেট্রিক চেক করেন। শার্ডেড সিস্টেমে আপনাকে অনুরোধটিকে শার্ডগুলোর ওপরে অনুসরণ করার পর্যবেক্ষণ দরকার।
প্রতি অনুরোধে করেলেশন আইডি ব্যবহার করুন এবং তা API লেয়ার থেকে রাউটার করে প্রতিটি শার্ডে প্রপাগেট করুন। এর সাথে ডিস্ট্রিবিউটেড ট্রেসিং জোড়া দিন যেন একটি স্ক্যাটার-গ্যাদার কোয়েরি কোন শার্ড স্লো করছে বা ফেল করছে তা দেখা যায়। মেট্রিক্সগুলোকে প্রতি-শার্ড ভেঙে রাখুন (লেটেন্সি, কিউ গভীরতা, এরর রেট), নাহলে একটি হট শার্ড ফ্লিটের গড়ের ভিতরে লুকিয়ে থাকবে।
ডেটা সঠিকতার ইনসিডেন্টস
শার্ডিং ব্যর্থতা প্রায়ই সঠিকতা বাগ আকারে দেখা দেয়:
- ডুপ্লিকেট রিট্রাই বা নন-আইডেমপটেন্ট লেখার পর
- রো অনুপস্থিত যখন মাইগ্রেশন ডেটা সরিয়েছে কিন্তু রাউটিং এখনও পুরোনো লোকেশনে পাঠায়
- স্প্লিট-ব্রেইন লেখাঃ দুইটি মেটাডেটা ভিউ একই কী রেঞ্জে লেখার অনুমতি দিলে দ্বন্দ্ব হতে পারে
ব্যাকআপ, রিস্টোর, ও ডিজাস্টার রিকভারি
"ডাটাবেস রিস্টোর করুন" হয়ে যায় "অনেক অংশকে সঠিক ক্রমে পুনঃগঠন করুন"। আপনাকে প্রথমে মেটাডেটা রিস্টোর করতে হতে পারে, তারপর প্রতিটি শার্ড, তারপর নিশ্চিত করতে হবে শার্ড বাউন্ডারি ও রাউটিং রুলস রিস্টোর পয়েন্ট-ইন-টাইম-এর সাথে মিলে। DR পরিকল্পনায় রিহার্সাল থাকা উচিত যেন আপনি প্রমাণ করতে পারেন কনসিস্টেন্ট ক্লাস্টার একত্রে পুনর্গঠন করতে পারবেন—শুধু আলাদা মেশিন পুনরুদ্ধার করা নয়।
কখন শার্ড করবেন না: বাস্তব বিকল্প ও সিদ্ধান্ত চেকলিস্ট
শার্ডিং প্রায়ই "স্কেলিং সুইচ" হিসেবে দেখা হয়, কিন্তু এটি স্থায়ীভাবে সিস্টেম জটিলতা বাড়ায়। যদি আপনি আপনার পারফরম্যান্স ও রিলায়েবিলিটি লক্ষ্য এক নোডেই পূরণ করতে পারেন, সাধারণত আপনি একটি সরল আর্কিটেকচার, সহজ ডিবাগিং, এবং কম অপারেশনাল এজ-কেস পাবেন।
বাস্তব বিকল্পগুলো যা অনেক হেডরুম দেয়
শার্ডিং করার আগে, এক নোড লজিকাল ডাটাবেস বজায় রেখে নিচের অপশনগুলো চেষ্টা করুন:
- ভাল ইনডেক্সিং + কোয়েরি টিউনিং: ধীর পথগুলো প্রথমে ঠিক করুন—মিসিং ইনডেক্স, অনবাউন্ডেড কোয়েরি, ব্যয়বহুল জয়েন, N+1 প্যাটার্নস।
- কেশিং: রিড-হেভি, স্থিতিশীল রেসপন্স ক্যাশে রাখুন (অ্যাপ-লেভেল ক্যাশ, CDN, ইন-মেমরি কাশ)
- রিড রেপ্লিকা: রিড ট্রাফিক অফলোড করুন লেখার পথ বদল না করেই (এবং যেখানে OK সেখানে রেপ্লিকা ল্যাগ মেনে নিন)
- এক নোডে টেবিল পার্টিশনিং: অনেক DB পার্টিশনিং সাপোর্ট করে যা মেইনটেইন্যান্স ও কোয়েরি পারফরম্যান্স বাড়ায় নোড বিভাজন ছাড়াই
কোথায় টুলস সাহায্য করে: শার্ড-অ্যাওয়ার সার্ভিস প্রোটোটাইপ করা
একটি বাস্তব উপায় ঝুঁকি কমাতে হচ্ছে প্লম্বিং (রাউটিং বাউন্ডারি, আইডেমপটেন্সি, মাইগ্রেশন ওয়ার্কফ্লো, পর্যবেক্ষণ) প্রোটোটাইপ করা আগে প্রোডাকশনে এগোনোর।
উদাহরণস্বরূপ, Koder.ai দিয়ে আপনি দ্রুত একটি ছোট বাস্তব সেবা স্পিন-আপ করতে পারেন—প্রায়ই একটি React অ্যাডমিন UI প্লাস একটি Go ব্যাকএন্ড ও PostgreSQL—এবং শার্ড-কী-অ্যাওয়ার API, আইডেমপটেন্সি কী, এবং কাটওভার আচরণগুলো স্যান্ডবক্সে পরীক্ষা করতে পারেন। Koder.ai পরিকল্পনা মোড, স্ন্যাপশট/রোলব্যাক এবং সোর্স কোড এক্সপোর্ট সমর্থন করে, তাই আপনি শার্ডিং-সংক্রান্ত ডিজাইন ডিসিশনগুলোকে পুনরাবৃত্তি করে প্রধান স্ট্যাক-এ নিয়ে যেতে পারেন যখন আপনি নিশ্চিত।
কখন শার্ডিং মানানসই (এবং কখন নয়)
শার্ডিং ভালো ফিট যখন আপনার ডেটাসেট বা লিখন থ্রুপুট এক নোডের সীমা স্পষ্টভাবে ছাড়িয়ে যায় এবং আপনার কোয়েরি প্যাটার্নগুলো নির্ভরযোগ্যভাবে একটি শার্ড কী দ্বারা রাউট করা যায় (কম ক্রস-শার্ড জয়েন, ন্যূনতম স্ক্যাটার-গ্যাদার)।
এটি খারাপ ফিট যখন আপনার প্রোডাক্টে অনেক অ্যাড-হক কোয়েরি, ঘনঘন মাল্টি-এন্টিটি ট্রাঞ্জেকশন, গ্লোবাল ইউনিকনেস কনস্ট্রেইন্ট দরকার, বা টিম অপারেশনাল ওয়ার্কলোড (রিব্যালান্সিং, রিশার্ডিং, ইনসিডেন্ট রেসপন্স) সামলাতে না পারে।
দ্রুত সিদ্ধান্ত চেকলিস্ট
জিজ্ঞেস করুন:
- ওয়ার্কলোড: বটলনেক কোথায়—CPU, I/O, মেমরি, না লক কনটেনশন—এবং তা কি শার্ড ছাড়া ঠিক করা যাবে?
- কোয়েরি প্যাটার্ন: ক্রিটিক্যাল কোয়েরিগুলোর 90%+ কি শার্ড কী দিয়ে রাউট করা যাবে?
- টিম ক্যাপাসিটি: কারা শার্ড ম্যাপ, অন-কল রানবুক, ও ক্রস-শার্ড ট্রাঞ্জেকশন আচরণ দেখভাল করবে?
- SLO: এক শার্ড ডাউন হলে আংশিক অবনতি এবং দীর্ঘ টেইল ল্যাটেন্সি কি সহ্য করা যাবে?
কেবল একটি ডায়াগ্রাম নয়—বৃদ্ধির জন্য পরিকল্পনা করুন
ভাইস-ভার্সে, শার্ডিং পিছিয়ে দিলেও, একটি মাইগ্রেশন পথ ডিজাইন করুন: এমন আইডেন্টিফায়ার বেছে নিন যা ভবিষ্যতে শার্ড কী হতে বাধা সৃষ্টি করবে না, এক-নোড ধারণাগুলো হার্ডকোড করা এড়িয়ে চলুন, এবং কিভাবে ডেটা ন্যূনতম ডাউনটাইমে সরাবেন তা অনুশীলন করুন। রিশার্ডিং পরিকল্পনা করার সেরা সময় হল প্রয়োজন হওয়ার আগেই।
সাধারণ প্রশ্ন
ডাটাবেস শার্ডিং কি, এবং এটি রেপ্লিকেশন থেকে কিভাবে আলাদা?
শার্ডিং (অনুভূমিক পার্টিশনিং) একটি একক লজিক্যাল ডেটাসেটকে একাধিক মেশিনে ভাগ করে—প্রত্যেকটি মেশিন বা ক্লাস্টার আলাদা রেকর্ড ধরে রাখে।
রেপ্লিকেশন তুলনায় ভিন্ন: রেপ্লিকেশন একই ডাটার প্রতিলিপি তৈরি করে উচ্চ প্রাপ্যতা এবং রিড স্কেলিং-এর জন্য।
একটি ডাটাবেস কেন বড় করা যাবে না, শার্ডিং কেন দরকার?
ভার্টিকাল স্কেলিং মানে একটি ডাটাবেস সার্ভারকে বড় করা (আরও CPU/RAM/দ্রুত ডিস্ক)। এটি অপারেশনally সহজ হতে পারে, কিন্তু শেষ পর্যন্ত সীমা থাকে এবং খরচ খুব দ্রুত বাড়ে।
শার্ডিং আউটস্কেল করে—নতুন মেশিন যোগ করে ক্ষমতা বাড়ায়—তবে এতে রাউটিং, রিব্যালান্সিং এবং ক্রস-শার্ড সঙ্গতি সম্পর্কিত নতুন জটিলতা আসে।
শার্ডিং আসলে কোন সমস্যা সমাধান করে?
টিমগুলো সাধারণত তখন শার্ড করে যখন একটি নোড নিয়মিতভাবে আটকে যায়, যেমন:
- ডিস্ক ও ইনডেক্স বৃদ্ধি করে ব্যাকআপ/মেন্টেইন্যান্স ধীর করে ফেলে
- লিখনের থ্রুপুট CPU/WAL/লক কনটেনশনে চ্যাপ্টা খায়
- রিড লোড প্রাইমারির উপর চাপ সৃষ্টি করে
- “নোইজি নেবর” কাস্টমার/ওয়ার্কলোড অন্যান্যদের পারফরম্যান্স খারাপ করে
শার্ডিং ডেটা ও ট্রাফিক ছড়িয়ে দেয় যাতে নোড যোগ করে ক্যাপাসিটি বাড়ানো যায়।
শার্ডেড ডাটাবেস সিস্টেমের মূল উপাদানগুলো কি কি?
একটি সাধারণ শার্ডেড সিস্টেমে থাকে:
- শার্ডস: আলাদা পার্টিশন, প্রত্যেকটি নিজের স্টোরেজ ও ইনডেক্স সঙ্গে
- রাউটার/কোঅর্ডিনেটর: কোন শার্ডে রিকুয়েস্ট পাঠাবেন তা নির্ধারণ করে
- মেটাডেটা/কনফিগ সার্ভিস: শার্ড ম্যাপ, মালিকানা, হেলথ, মেমবারশিপ ইত্যাদি
- ব্যাকগ্রাউন্ড জবস: রিব্যালান্সিং, মাইগ্রেশন, ব্যাকআপ/রিস্টোর ওয়ার্কফ্লো
পারফরম্যান্স ও সঠিকতা এই অংশগুলো কিভাবে সমন্বয় করে তার উপর নির্ভর করে।
শার্ড কী কি, এবং এটা কেন এত গুরুত্বপূর্ণ?
শার্ড কী হল সেই ফিল্ড(বা ফিল্ডগুলোর কম্বিনেশন) যা ব্যবহার করে সিস্টেম সিদ্ধান্ত নেয় কোন শার্ডে একটি রো থাকবে। এটি বেশিরভাগ ক্ষেত্রে নির্ধারণ করে যে অনুরোধটি এক শার্ডে যাবে (দ্রুত) না অনেক শার্ডে ছড়িয়ে পড়বে (ধীর)।
ভাল শার্ড কী সাধারণত থাকে: উচ্চ কার্ডিনালিটি, সমান বণ্টন, এবং আপনার প্রচলিত অ্যাক্সেস প্যাটার্নের সাথে অনুকূলতা (উদাহরণ: tenant_id বা user_id)।
কোন গুণগুলো একটি শার্ড কী-কে “খারাপ” বানায়, এবং তা কী সমস্যা তৈরি করে?
খারাপ শার্ড কী-এর উদাহরণ:
- মোনোটনিক/টাইম-ভিত্তিক কী (নতুন ডেটা সর্বশেষ শার্ডে জমে হটস্পট তৈরি করে)
- কম-কার্ডিনালিটি ফিল্ড (অল্প ভ্যালু → অসম লোড)
- পরিবর্তনশীল আইডি (ইমেইল বা mutable username—কী বদলালে ডেটা শার্ড বদলাতে হয়)
এগুলো সাধারণত হটস্পট বা রুটিং ছড়িয়ে দেওয়ার কারণ হয়, ফলে রুট করা কোয়েরিগুলো স্ক্যাটার-গ্যাদারে পরিণত হতে পারে।
রেঞ্জ, হ্যাশ, এবং ডিরেক্টরি শার্ডিং কি, এবং কখন কোনটি ব্যবহার করবেন?
প্রচলিত স্ট্র্যাটেজিগুলো হল:
- রেঞ্জ শার্ডিং: একটি কী-স্পেসের ধারাবাহিক রেঞ্জ শার্ডগুলোর মধ্যে ভাগ করা—রাউটিং সহজ, কিন্তু টাইম-ভিত্তিক বা একপেশে বৃদ্ধি হলে হটস্পট হয়
- হ্যাশ শার্ডিং: কী-এর উপর হ্যাশ রেখে শার্ড নির্দিষ্ট করা—সমান বণ্টন দেয়, কিন্তু রেঞ্জ কোয়েরি খারাপ করে তোলে; কনসিস্টেন্ট হ্যাশিং ব্যবহার করে রেশফাফল কমানো যায়
- ডিরেক্টরি/লুকআপ শার্ডিং: একটি বাইরের ম্যাপে কী → শার্ড স্টোর করা থাকে—সবচেয়ে নমনীয়, কিন্তু একটি বাড়তি নির্ভরতা যোগ করে
অনেক বাস্তব সিস্টেম মিশ্র পদ্ধতি (কম্পোজিট কী, সাব-শার্ডিং) ব্যবহার করে।
কেন কিছু কোয়েরি শার্ড করার পর ধীর হয়ে যায় (স্ক্যাটার-গ্যাদার)?
যদি কোয়েরি শার্ড কী দিয়ে রাউট করা যায়, তখন তা এক শার্ডে পাঠানো যায়—দ্রুত পথ।
কিন্তু যদি রাউট করা না যায়, সিস্টেম অনেক বা সব শার্ডে কোয়েরি ছড়িয়ে দেয় (স্ক্যাটার-গ্যাদার)। প্রতিটি শার্ড স্থানীয়ভাবে কোয়েরি চালায়, তারপর রাউটার ফলাফল মেড়্জ করে—এতে টেইল ল্যাটেন্সি বাড়ে: একটি ধীর শার্ড পুরো অনুরোধকে আটকে দিতে পারে।
শার্ডিং-এ লেখাপড়া এবং ট্রাঞ্জেকশনগুলো কিভাবে কাজ করে?
একটি শার্ড-সীমাবদ্ধ লেখার ক্ষেত্রে স্বাভাবিক ট্রাঞ্জেকশান কাজ করে।
কিন্তু যখন আপডেট একাধিক শার্ড জুড়ে লাগে, তখন ডিস্ট্রিবিউটেড ট্রাঞ্জেকশন দরকার হয়—যা দুই-ফেজ কমিটের মতো প্রটোকল ব্যবহার করে, দেরি বাড়ায় এবং ব্যর্থতার অমীমাংসিত অবস্থা সৃষ্টি করে।
প্রচলিত পদ্ধতিগুলো ক্রস-শার্ড লেখার প্রয়োজন কমায়:
- ডেটা লোকালিটি বজায় রাখা (সম্পর্কিত রেকর্ড এক শার্ডে রাখা)
- অপারেশনগুলোকে এক শার্ডই “অধিকারী” হিসেবে ডিজাইন করা
- ডেনর্মালাইজেশন করা
এবং লিখনকে idempotent করা জরুরি—অপারেশন আইডি রেখে রিট্রাই সেফ করা।
কনসিস্টেন্সি এবং রেপ্লিকেশন শার্ডিং-এ কিভাবে বজায় থাকে?
প্রতিটি শার্ড সাধারণত প্রতিলিপি করে—একটি লিডার লিখন গ্রহণ করে, এক বা একাধিক রেপ্লিকা কপি করে। লিডার পড়া/লিখা নিশ্চিতকরণ না করা পর্যন্ত কিছু রিডগুলি পুরোনো ডেটা দেখাতে পারে (রেপ্লিকা ল্যাগ)।
সাধারণত শার্ডিং-এ আপনি দেখতে পাবেন: শার্ডের ভেতর শক্তিশালী কনসিস্টেন্সি আর শার্ডগুলোর মধ্যে ঢিলে-ঢালে কনসিস্টেন্সি বা দুর্বল গ্যারান্টি।
গ্লোবাল কনস্ট্রেন্টস (এমনকি uniqueness, foreign keys, global counters) প্রয়োজনে কেন্দ্রীভূত সমাধান বা অ্যাপ-লেভেল ওয়ার্কফ্লো লাগে—এগুলো প্রোডাক্টের জন্য কি "সঠিক" তা নির্ধারণ করে।
কোনও ডাউনটাইম ছাড়াই রিব্যালান্সিং বা রিশার্ডিং কিভাবে করা যায়?
রিব্যালান্সিং তখন প্রয়োজন যখন ডেটা বা ট্রাফিক অসমভাবে বেড়ে যায়, নতুন নোড যোগ করা হয়, বা হার্ডওয়্যার অবসর নেওয়া দরকার হয়।
অনলাইন মাইগ্রেশনের সাধারণ ধাপ:
- কপি: সোর্স থেকে টার্গেটে ব্যাকফিল করুন সরাসরি সার্ভিং চললেও
- ডুয়াল-রাইট (এখন কখনও কখনও ডুয়াল-রিড): ট্রানজিশনে নতুন পরিবর্তন উভয় পাশে লিখুন
- কাটওভার: শার্ড ম্যাপ আপডেট করে ট্রাফিক নতুন লোকেশনে পাঠান
- ক্লিনআপ: পুরানো কপি মুছে ফেলুন ও স্পেস রিক্লেইম করুন
ক্লায়েন্ট-ক্যাশিং ও রাউটিং মেটাডেটা সংস্করণ করা, রিলফ্রেশ পরিকল্পনা এবং রোলব্যাক পরিকল্পনা থাকা জরুরি।
হটস্পট এবং স্কিউ কি, এবং এগুলো কখন ঘটে?
হটস্পট হলো যখন কীগুলোর একটি ছোট অংশ ট্রাফিকের বেশিরভাগ টেনে নিয়ে যায়—উদাহরণস্বরূপ একটি সেলিব্রিটি অ্যাকাউন্ট বা আজকের টাইম-ভিত্তিক কী।
স্কিউ অন্তর্ভুক্ত করে:
- ডেটা স্কিউ: একটি শার্ডে বেশি বাইট/রো থাকে (স্টোরেজ প্রেসার)
- ট্রাফিক স্কিউ: এক শার্ডের কাছে বেশি QPS বা ভারি কোয়েরি যায় (CPU স্যাচুরেশন)
ডিটেকশনের জন্য প্রতিটি শার্ডের উপর ভিত্তিক ড্যাশবোর্ড দেখুন: p95 latency, QPS, স্টোরেজ ইউসেজ।
মিটিগেশন: শার্ড কী পরিবর্তন করে ট্রাফিক ভারসাম্য করা, বকেটিং/সাল্টিং, ক্যাশিং, রেট-লিমিট বা হট শার্ড স্প্লিট/মুভ করা।
শার্ডেড সিস্টেমে কোন ধরনের ব্যর্থতা দেখা যায় এবং কীভাবে ডিবাগ করবেন?
শার্ডিং নতুন ধরনের ব্যর্থতা যুক্ত করে—একটি শার্ড ডাউন হলে আংশিক আউটেজ হতে পারে, রাউটার ভুল রাউট করলে খালি রেজাল্ট দেখা যেতে পারে, অথবা মেটাডেটা অপ্রস্তুত থাকলে সিস্টেম কোথায় ডেটা আছে সে সম্পর্কে দ্বন্দ্ব করতে পারে।
ডিবাগ করতে: প্রতিটি অনুরোধে করেলেশন আইডি প্রয়োগ করুন, ডিস্ট্রিবিউটেড ট্রেসিং ব্যবহার করুন, এবং মেট্রিক্সকে প্রতি-শার্ড ভাঙা রাখুন। ব্যাকআপ/রিস্টোর পদ্ধতিতে মেটাডেটা প্রথমে ফেরত আনা উচিত যাতে শার্ড-বাউন্ডারিগুলো মিল থাকে।
কখন শার্ডিং এড়ানো উচিত, এবং বাস্তব বিকল্পগুলো কি কি?
শার্ডিং স্থায়ীভাবে জটিলতা বাড়ায়—তাই সম্ভব হলে বিকল্পগুলো আগে চেষ্টা করুন:
- সূচক ও কোয়েরি টিউনিং
- ক্যাশিং
- রিড রেপ্লিকা (রেপ্লিকা ল্যাগ মেনে নিয়ে)
- এক নোডে টেবিল পার্টিশনিং
- পুরনো ডেটা আর্কাইভ করা
শার্ডিং উপযুক্ত যখন একটি নোড স্পষ্টভাবে সীমা ছাড়িয়ে যায় এবং আপনার ক্রিটিক্যাল কোয়েরিগুলোর 90%+ শার্ড-কি দ্বারা রাউটেবল।