অ্যামাজন DynamoDB ব্যাখ্যা: স্কেলযোগ্য সিস্টেম তৈরি
জানুন Amazon DynamoDB কী, এর NoSQL মডেল কিভাবে কাজ করে, এবং স্কেলযোগ্য, কম-ল্যাটেন্সির সিস্টেম ও মাইক্রোসার্ভিস ডিজাইনের বাস্তবিক প্যাটার্নগুলো কী।

DynamoDB কী এবং কেন দলগুলো এটি ব্যবহার করে
অ্যামাজন DynamoDB হলো AWS-এর একটি ফুলি-ম্যানেজড NoSQL ডাটাবেস সার্ভিস, যা এমন অ্যাপলিকেশনগুলোর জন্য তৈরি করা হয়েছে যেগুলোকে প্রায় যে কোনো স্কেলে ধারাবাহিকভাবে কম ল্যাটেন্সির রিড ও রাইট দরকার। “ফুলি-ম্যানেজড” মানে AWS ইনফ্রাস্ট্রাকচার কাজগুলো—হার্ডওয়্যার প্রোভিশনিং, রেপ্লিকেশন, প্যাচিং, এবং অনেক অপারেশনাল কাজ—হ্যান্ডেল করে, যাতে দলগুলো ডাটাবেস সার্ভার চালানোর পরিবর্তে ফিচার ডেলিভারিতে ফোকাস করতে পারে।
মূলত DynamoDB ডেটা items (রো) হিসেবে tables-এ সঞ্চয় করে, কিন্তু প্রতিটি আইটেমে নমনীয় অ্যাট্রিবিউট থাকতে পারে। ডেটা মডেলটিকে নিম্নোক্তভাবে বুঝলে সুবিধা হয়:
- Key-value: প্রাইমারি কী দিয়ে দ্রুত একটা আইটেম ফেচ করা যায়, ঠিক যেমন কোন ID দিয়ে রেকর্ড খোঁজা।
- Document: নেস্টেড অ্যাট্রিবিউট (maps ও lists) রাখা যায়, JSON-এর মতো, যা সম্পর্কিত ফিল্ডগুলোতে স্ট্রিক্ট স্কিমা ছাড়াই কাজ করে।
দলগুলো DynamoDB বেছে নেয় যখন তারা পূর্বানুমানযোগ্য পারফরম্যান্স এবং সহজ অপারেশন চায় এমনও ওয়ার্কলোডের জন্য যা রিলেশনাল জয়েনে ঠিকভাবে ফিট করে না। এটা সাধারণত মাইক্রোসার্ভিস (প্রতিটি সার্ভিস তার নিজস্ব ডেটা মালিকানায় রাখে), সার্ভারলেস অ্যাপ যেখানে ট্রাফিক স্পাইক হয়, এবং এমন ইভেন্ট-ড্রিভেন সিস্টেমে ব্যবহৃত হয় যেগুলি ডেটার পরিবর্তনে প্রতিক্রিয়া করে।
এই পোস্টে টেবিল, কী, ইনডেক্স—এসব বিল্ডিং ব্লক, অ্যাক্সেস প্যাটার্ন অনুযায়ী মডেলিং (সিঙ্গল-টেবিল ডিজাইন সহ), স্কেলিং ও ক্যাপাসিটি মোড কিভাবে কাজ করে, এবং স্ট্রিমিং পরিবর্তনগুলো ইভেন্ট-ড্রিভেন আর্কিটেকচারে কিভাবে ব্যবহার করা যায়—এসব আলোচনা করা হবে।
কোর কনসেপ্ট: টেবিল, আইটেম, এবং প্রাইমারি কী
DynamoDB কয়েকটি সহজ বিল্ডিং ব্লকের চারপাশে সংগঠিত, কিন্তু বিবরণগুলো গুরুত্বপূর্ণ কারণ সেগুলোই নির্ধারণ করে আপনি কীভাবে ডেটা মডেল করবেন এবং কোন অনুরোধগুলো কত দ্রুত (এবং খরচ-কার্যকরভাবে) চলে।
টেবিল, আইটেম, এবং অ্যাট্রিবিউট
একটি টেবিল হলো টপ-লেভেল কনটেইনার। টেবিলের প্রতিটি রেকর্ড একটি আইটেম (রো-এর সমতুল্য), এবং প্রতিটি আইটেম হলো একটি সেট অ্যাট্রিবিউট (কলামের মত)।
রিলেশনাল ডাটাবেসের মতো নয়—একই টেবিলের আইটেমগুলোর একই অ্যাট্রিবিউট থাকা বাধ্যতামূলক নয়। একটি আইটেমে {status, total, customerId} থাকতে পারে, আর অন্যটিতে {status, shipmentTracking}—DynamoDB-তে ফিক্সড স্কিমা লাগে না।
প্রাইমারি কী: সরল বনাম কম্পোজিট
প্রতিটি আইটেম অনন্যভাবে শনাক্ত হয় একটি প্রাইমারি কীর মাধ্যমে, এবং DynamoDB দুটি ধরনের সমর্থন করে:
- সরল প্রাইমারি কী (শুধু partition key): একটি অ্যাট্রিবিউট প্রতিটি আইটেমকে অনন্যভাবে নির্ধারণ করে।
- কম্পোজিট প্রাইমারি কী (partition key + sort key): একাধিক আইটেম একই partition key শেয়ার করতে পারে, আর sort key সেগুলোকে আলাদা করে এবং ওই partition-ভিত্তিক অর্ডার নির্ধারণ করে।
প্র্যাকটিসে, কম্পোজিট কী “গ্রুপ করা” অ্যাক্সেস প্যাটার্ন যেমন “একই গ্রাহকের সব অর্ডার, নতুনতম প্রথম” এর সুবিধা দেয়।
Query বনাম Scan (উচ্চ স্তরে)
Query আইটেম পড়ে প্রাইমারি কী (বা ইনডেক্স কী) দ্বারা। এটি একটি নির্দিষ্ট partition key লক্ষ্য করে এবং sort key রেঞ্জ দিয়ে ফিল্টার করতে পারে—এটাই দক্ষ এবং প্রেফার করা পথ।
Scan পুরো টেবিল (বা ইনডেক্স) ধরে হাঁটে এবং পরে ফিল্টার করে। শুরুতে সহজ, কিন্তু স্কেলে সাধারণত ধীর এবং ব্যয়বহুল।
মনে রাখার মত সীমা
কিছু কনস্ট্রেইন্ট আছে যা শুরুতেই অনুভব করবেন:
- Max item size: 400 KB।
- Attribute types: scalars (string/number/binary/boolean/null), sets, lists, এবং maps।
- Key attributes অবশ্যই scalar হতে হবে (partition বা sort key হিসেবে lists/maps ব্যবহার করা যাবে না)।
এই ভিত্তি গুলোই পরবর্তী অংশ—অ্যাক্সেস প্যাটার্ন, ইনডেক্সিং পছন্দ, এবং পারফরম্যান্স বৈশিষ্ট্য—নির্ধারণ করে।
DynamoDB-এর ডেটা মডেল: কী-ভ্যালু ও ডকুমেন্ট
DynamoDB প্রায়ই কেও-ভ্যালু স্টোর এবং ডকুমেন্ট ডাটাবেস উভয় হিসেবেই বর্ণনা করা হয়। এটা সঠিক, কিন্তু প্রতিদিনের ডিজাইনে প্রতিটির অর্থ কী তা বোঝা কাজে লাগে।
কী-ভ্যালু অ্যাক্সেস বনাম ডকুমেন্ট-স্টাইল আইটেম
মূলত আপনি কী দিয়ে ডেটা রিটার্ন করেন। প্রাইমারি কী মান প্রদান করলে DynamoDB একটি একক আইটেম ফেরত দেয়। সেই কী-ভিত্তিক লুকআপই অনেক ওয়ার্কলোডে পূর্বানুমানযোগ্য, কম-ল্যাটেন্সি স্টোরেজ দেয়।
একই সাথে, একটি আইটেমে নেস্টেড অ্যাট্রিবিউট (maps ও lists) থাকতে পারে, যা এটিকে ডকুমেন্ট ডাটাবেসের মতো অনুভব করায়: আপনি স্ট্রিক্ট স্কিমা ছাড়াই স্ট্রাকচার্ড পে-লোড সংরক্ষণ করতে পারেন।
আইটেমে হায়ারারকিকাল JSON-সদৃশ কাঠামো মডেলিং
আইটেমগুলো স্বাভাবিকভাবেই JSON-সদৃশ ডেটার সাথে মানানসই:
- Maps অবজেক্টকে প্রতিনিধিত্ব করে (উদাহরণ:
profile.name,profile.address)। - Lists অ্যারে প্রতিনিধিত্ব করে (উদাহরণ: সাম্প্রতিক অ্যাকশন, ট্যাগ)।
যখন একটি এন্টিটি সাধারণত পুরোটা পড়ে পাওয়া যায়—যেমন ইউজার প্রোফাইল, শপিং কার্ট, বা কনফিগারেশন বান্ডল—তখন এটি খুব ভাল ফিট করে।
কখন ডেনরমালাইজ করা উচিত (এবং কেন প্রচলিত)
DynamoDB সার্ভার-সাইড জয়েন সমর্থন করে না। যদি আপনার অ্যাপকে “একটি অর্ডার এবং তার লাইন আইটেম ও শিপিং স্ট্যাটাস” একবারে ফেরত দিতে হয়, আপনি প্রায়ই ডেনরমালাইজ করবেন: কিছু অ্যাট্রিবিউট কপিই করে বিভিন্ন আইটেমে রাখবেন, বা ছোট সাবস্ট্রাকচারগুলি সরাসরি একটি আইটেমে এমবেড করবেন।
রিলেশনাল নরমালাইজেশনের বিপরীতে ট্রেড-অফ
ডেনরমালাইজেশন লেখার জটিলতা বাড়ায় এবং আপডেট ফ্যান-আউট তৈরি করতে পারে। বিনিময়ে আপনি কম রাউন্ড-ট্রিপ এবং দ্রুত রিড পান—প্রায়শই স্কেলযোগ্য সিস্টেমে এটাই গুরুত্বপূর্ণ।
Partition Key এবং Sort Key: অ্যাক্সেস প্যাটার্ন অনুযায়ী ডিজাইন
সবচেয়ে দ্রুত DynamoDB কুয়েরিগুলো হলো যেগুলো আপনি “এই partition দিন” (এবং ঐ partition-ভিত্তিকভাবে “এই রেঞ্জ দিন”) এইভাবে প্রকাশ করতে পারেন। তাই কী চয়েস মূলত আপনি কিভাবে পড়বেন তা নিয়ে—শুধুমাত্র স্টোর করার উপায় নয়।
Partition key: ডাটা বিতরণ ও পূর্বানুমানযোগ্য রিড
Partition key নির্ধারণ করে কোন ফিজিক্যাল পার্টিশনে একটি আইটেম সংরক্ষিত হবে। DynamoDB এই মানটি হ্যাশ করে ডেটা ও ট্রাফিক ছড়িয়ে দেয়। যদি অনেক অনুরোধ কয়েকটি partition key মানের উপর কেন্দ্রীভূত হয়, আপনি “হট” পার্টিশন তৈরি করবেন এবং থ্রুপুট সীমা পেরিয়ে যাবেন যদিও টেবিলটা মোটামুটিidle।
ভাল partition key:
- উচ্চ কার্ডিনালিটি (অনেক আলাদা মান) থাকে
- একটি ঘটনাবহুল অ্যাক্সেস প্যাটার্নের সাথে মেলে (এবং তাই রিডগুলো সরাসরি হয়, না ফিল্টারকৃত)
- এমন মান এড়ায় যা জনপ্রিয় হয়ে যায় (যেমন
"GLOBAL"-এর মতো কন্সট্যান্ট)
Sort key: রেঞ্জ কুয়েরি ও গ্রুপেড এন্টিটি
Sort key থাকলে একই partition key শেয়ার করা আইটেমগুলো একসাথে রাখা হয় এবং sort key দ্বারা অর্ডার করা হয়। এটি দক্ষভাবে সক্ষম করে:
- রেঞ্জ কুয়েরি (
BETWEEN,begins_with) - টাইম-অর্ডারড রিড (রিভার্স স্ক্যান করে newest-first)
- এন্টিটি গ্রুপিং (একই partition key-এ একাধিক আইটেম টাইপ)
কমন প্যাটার্ন হলো sort key কম্পোজিট করা, যেমন TYPE#id বা TS#2025-12-22T10:00:00Z, যাতে একাধিক কুয়েরি শেপ সহায়ক হয় আলাদা টেবিল ছাড়া।
কমন অ্যাক্সেস প্যাটার্নগুলো কী-এ ম্যাপ করা
- Get by ID:
PK = USER#<id>(সরলGetItem) - List by user:
PK = USER#<id>,SK begins_with ORDER#(অথবাSK = CREATED_AT#...) - Time-series ranges:
PK = DEVICE#<id>,SK = TS#<timestamp>এবংBETWEENদিয়ে টাইম উইন্ডোগুলি
কী চয়েস কিভাবে পারফরম্যান্স ও স্কেলেবল করছে
যদি আপনার partition key আপনার সর্বোচ্চ-ভলিউম কুয়েরিগুলোর সাথে মেলে এবং ভালোভাবে বিতরণ করে, আপনি ধারাবাহিকভাবে কম-ল্যাটেন্সির রিড ও রাইট পাবেন। যদি না করে, আপনি Scan, ফিল্টার, বা অতিরিক্ত ইনডেক্স দিয়ে ক্ষতিপূরণ করবেন—প্রতিটাই খরচ বাড়ায় এবং হট কীয়ের ঝুঁকি বাড়ায়।
সেকেন্ডারি ইনডেক্স: GSI ও LSI ব্যাখ্যা
সেকেন্ডারি ইনডেক্স DynamoDB-কে আপনার টেবিলের প্রাইমারি কী ছাড়াও বিকল্প কুয়েরি পথ দেয়। প্রতিবার যে নতুন অ্যাক্সেস প্যাটার্ন আসে তখন পুরো বেস টেবিল পরিবর্তন না করে, আপনি একটি ইনডেক্স যোগ করে একই আইটেমগুলোকে ভিন্ন কী দিয়ে কুয়েরি করতে পারবেন।
GSI বনাম LSI: পার্থক্য কী?
Global Secondary Index (GSI)-এর নিজস্ব partition key (এবং ঐচ্ছিক sort key) থাকে যা টেবিলটির থেকে সম্পূর্ণ আলাদা হতে পারে। এটা “গ্লোবাল” কারণ এটি সমস্ত টেবিল পার্টিশন জুড়ে বিস্তৃত এবং যেকোন সময় যোগ বা মুছে ফেলা যায়। নতুন অ্যাক্সেস প্যাটার্নের জন্য GSI ব্যবহার করুন যখন মূল কী ডিজাইনের সাথে তা মেলে না—উদাহরণ: টেবিল যদি orderId দ্বারা কিও করা থাকে কিন্তু আপনি customerId দ্বারা কুয়েরি করতে চান।
Local Secondary Index (LSI) বেস টেবিলের সাথে একই partition key শেয়ার করে কিন্তু আলাদা sort key ব্যবহার করে। LSI টেবিল তৈরির সময় সংজ্ঞায়িত করতে হয়। এগুলো তখন উপযোগী যখন আপনি একই এন্টিটি গ্রুপের মধ্যে একাধিক sort অর্ডার চান (যেমন গ্রাহকের অর্ডারগুলো createdAt বনাম status দ্বারা সাজানো করে পাওয়া)।
Projections: ইনডেক্সে কী কপি করা হয়
প্রজেকশন নির্ধারণ করে কোন অ্যাট্রিবিউটগুলো ইনডেক্সে রাখা হবে:
- KEYS_ONLY: সস্তা স্টোরেজ, কিন্তু প্রায়শই বেস টেবিল থেকে অতিরিক্ত রিড লাগবে।
- INCLUDE: শুধুমাত্র সাধারণত রিটার্ন করা অ্যাট্রিবিউটগুলো কপি করুন।
- ALL: সহজতম, কিন্তু স্টোরেজ ও লেখার খরচ বাড়াতে পারে।
Write amplification (গোপন বিল)
বেস টেবিলে প্রতিটি লেখা এক বা একাধিক ইনডেক্সে লেখাকে ট্রিগার করতে পারে। বেশি GSI এবং বড় প্রজেকশন লেখার খরচ ও ক্যাপাসিটি ব্যবহার বাড়ায়। স্থিতিশীল অ্যাক্সেস প্যাটার্ন অনুযায়ী ইনডেক্স পরিকল্পনা করুন, এবং সম্ভব হলে প্রজেক্ট হওয়া অ্যাট্রিবিউটগুলো ন্যূনতম রাখুন।
ক্যাপাসিটি মোড ও স্কেলিং আচরণ
DynamoDB স্কেলিং শুরু হয় একটি পছন্দ দিয়ে: On-Demand বা Provisioned ক্যাপাসিটি। দুইই খুব উচ্চ থ্রুপুটে পৌঁছতে পারে, কিন্তু পরিবর্তনশীল ট্রাফিকে তারা আলাদা ভাবে আচরণ করে।
On-Demand বনাম Provisioned: কিভাবে নির্বাচন করবেন
On-Demand সহজ: আপনি অনুরোধ ভিত্তিতে bezahlen করেন এবং DynamoDB স্বয়ংক্রিয়ভাবে পরিবর্তনশীল লোড সামলায়। এটি অনিয়মিত ট্রাফিক, প্রারম্ভিক পণ্যের জন্য, এবং স্পাইকী ওয়ার্কলোডের জন্য ভাল যেখানে আপনি ক্যাপাসিটি লক্ষ্য পরিচালনা করতে চান না।
Provisioned হল ক্যাপাসিটি পরিকল্পনা: আপনি রিড ও রাইট থ্রুপুট নির্দিষ্ট করেন (বা auto-scale করেন) এবং স্থিতিশীল প্রয়োগে আরও পূর্বানুমানযোগ্য মূল্যমান পান। এটি পরিচিত, স্থিতিশীল ওয়ার্কলোডের জন্য সাধারণত সস্তা।
রিড/রাইট ক্যাপাসিটি বাস্তবে
Provisioned থ্রুপুট পরিমাপ করা হয়:
- RCUs (Read Capacity Units): প্রায় এক strongly consistent রিড প্রতি সেকেন্ডে 4 KB পর্যন্ত (অথবা দুইটি eventually consistent রিড)।
- WCUs (Write Capacity Units): প্রায় এক রাইট প্রতি সেকেন্ডে 1 KB পর্যন্ত।
আপনার আইটেম সাইজ ও অ্যাক্সেস প্যাটার্ন বাস্তব খরচ নির্ধারণ করে: বড় আইটেম, স্ট্রং কনসিস্টেন্সি, এবং স্ক্যান দ্রুতই ক্যাপাসিটি পোড়াতে পারে।
Auto scaling মৌলিক ধারণা (এবং সীমা)
Auto scaling ব্যবহারিকভাবে provisioned RCUs/WCUs-কে ইউটিলাইজেশন লক্ষ্য অনুযায়ী অ্যাডজাস্ট করে। এটি ধীর বৃদ্ধি বা পূর্বানুমানযোগ্য সাইকেলের জন্য সাহায্য করে, কিন্তু তা মুহূর্তে নয়। হঠাৎ স্পাইকে ক্যাপাসিটি যথেষ্ট দ্রুত না বাড়লে থ্রটলিং হওয়ার ফলে সমস্যা হতে পারে, এবং এটা হট পার্টিশন ঠিক করতে পারে না।
DAX: রিড-হেভি ওয়ার্কলোডের জন্য ক্যাশিং
DynamoDB Accelerator (DAX) হলো একটি ইন-মেমরি ক্যাশ যা রিড ল্যাটেন্সি কমাতে এবং পুনরাবৃত্ত রিডগুলো অফলোড করতে পারে (উদাহরণ: জনপ্রিয় প্রোডাক্ট পেজ, সেশন লুকআপ, লিডারবোর্ড)। এটা বেশি উপকারী যখন অনেক ক্লায়েন্ট একই আইটেম বারবার চাই; এটি রাইট-হেভি প্যাটার্নে সহায়ক নয়, এবং ভালো কী ডিজাইনকে প্রতিস্থাপন করে না।
কনসিস্টেন্সি, ট্রানজেকশন, ও সঠিকতা
DynamoDB আপনাকে রিড গ্যারান্টি বনাম ল্যাটেন্সি ও খরচের মধ্যে ট্রেড-অফ করতে দেয়, তাই প্রতি অপারেশনের "সঠিকতা" কী তা স্পষ্ট করা গুরুত্বপূর্ণ।
Eventually consistent বনাম strongly consistent রিড
ডিফল্টভাবে, GetItem ও Query eventually consistent রিড ব্যবহার করে: লেখার পরে সামান্য সময়ের জন্য পুরোনো মান দেখা যেতে পারে। এটি প্রায়শই ফিড, প্রোডাক্ট ক্যাটালগ, এবং অন্যান্য রিড-মোস্টলি ভিউগুলোর জন্য ঠিক থাকে।
Strongly consistent রিড (একটি অপশন, একই রিজিয়নের বেস টেবিল থেকে) গ্যারান্টি দেয় যে আপনি সর্বশেষ নিশ্চিত লেখাই দেখবেন। স্ট্রং কনসিস্টেন্সি বেশি রিড ক্যাপাসিটি খরচ করে এবং টেইল ল্যাটেন্সি বাড়াতে পারে, তাই শুধুমাত্র অত্যাবশ্যক রিডগুলোর জন্য ব্যবহার করুন।
কখন strong consistency জরুরি
Strong consistency দরকার হতে পারে এমন পরিস্থিতি:
- অর্ডার কনফার্মের আগে ইনভেন্টরি চেক করা
- একসেস দেওয়ার আগে অথORIZATION ফ্ল্যাগ পড়া
- ওয়ার্কফ্লো স্টেট পড়ে পরবর্তী ধাপ চালানো
কাউন্টারগুলোর জন্য, সবচেয়ে নিরাপদ পদ্ধতি সাধারণত “strong read then write” নয়, বরং অ্যাটমিক আপডেট (যেমন UpdateItem সাথে ADD) যাতে ইনক্রিমেন্ট হারিয়ে না যায়।
ট্রানজেকশনাল রিড/রাইট
DynamoDB ট্রানজেকশন (TransactWriteItems, TransactGetItems) ACID সেমান্টিক্স প্রদান করে সর্বোচ্চ 25 আইটেম পর্যন্ত। এগুলো ব্যবহার করুন যখন আপনাকে একাধিক আইটেম একসঙ্গে আপডেট করতে হবে—যেমন অর্ডার লেখা এবং ইনভেন্টরি রিজার্ভ করা—অথবা এমন ইনভারিয়েন্ট যা আংশিক স্টেটে সহ্য করতে পারে না।
নিরাপদ রিট্রাইগুলোর জন্য আইডেমনপোটেন্সি
রিট্রাইগুলি ডিসট্রিবিউটেড সিস্টেমে স্বাভাবিক। লিখাগুলো idempotent করুন যাতে রিট্রাই ডুপ্লিকেট এফেক্ট তৈরি না করে:
- একটি client request token (idempotency key) ব্যবহার করুন এবং ফলাফলের সঙ্গে এটি সংরক্ষণ করুন
ConditionExpressionদিয়ে অনন্যতা নিশ্চিত করুন (যেমনattribute_not_exists)\n- রিড-Modify-রাইট লুপের পরিবর্তে অ্যাটমিক আপডেট প্রাধান্য দিন
DynamoDB-এ সঠিকতা মূলত সঠিক consistency লেভেল বাছাই এবং এমন অপারেশন ডিজাইন করার উপর নির্ভর করে যাতে রিট্রাই ডেটা ভঙ্গ করে না।
পার্টিশন, হট কী, এবং ট্রাফিক স্পাইক
DynamoDB টেবিলের ডেটা একাধিক ফিজিক্যাল পার্টিশনে সংরক্ষণ করে। প্রতিটি পার্টিশনের পড়া/লেখার জন্য সীমিত থ্রুপুট এবং কতটা ডেটা রাখা যাবে তার সীমা আছে। আপনার partition key নির্ধারণ করে আইটেম কোথায় থাকে; যদি খুব বেশি অনুরোধ একই partition key (বা কয়েকটি মান) লক্ষ্য করে, সেই পার্টিশনই বটলনেক হয়ে যাবে।
হট পার্টিশন কেন হয়
হট পার্টিশন সাধারণত কী-বেছে নেয়ার কারণে ঘটে: একটি “গ্লোবাল” partition key যেমন USER#1, TENANT#default, বা STATUS#OPEN, অথবা টাইম-অর্ডারড প্যাটার্ন যেখানে সবাই একটিভ “এখন” লেখে এক partition এ।
হট কী ও অপ্রতুল ট্রাফিকের লক্ষণ
সাধারণত আপনি দেখতে পাবেন:
- কোনো নির্দিষ্ট কী জন্য থ্রটলিং (
ProvisionedThroughputExceededException) - কিছু অ্যাক্সেস প্যাটার্নে স্পাইকিং ল্যাটেন্সি অন্যরা ভালো থাকা সত্ত্বেও
- CloudWatch মেট্রিক্সে অনিয়মিত কনসাম্ড ক্যাপাসিটি ও আকস্মিক বুর্স দেখা
প্রশমন কৌশল
প্রথমে বিতরণের জন্য ডিজাইন করুন, পরে কুয়েরি সুবিধার্থে:
- Key design: উচ্চ-কার্ডিনালিটি partition key নিশ্চিত করুন (যেমন
TENANT#<id>কনস্ট্যান্টের বদলে) - Write sharding: ছোট র্যান্ডম বা হ্যাশ সাফল/প্রিফিক্স যোগ করুন যেমন
ORDER#<id>#<shard>যাতে N শার্ডে লেখা ছড়ায়, এবং প্রয়োজন হলে শার্ড জুড়ে কুয়েরি করুন - Time buckets: ঘন্টা/দিন দ্বারা বকেৎ করুন (
METRIC#2025-12-22T10) যাতে “সব লেখানো সর্বশেষ আইটেমে” নাহয়
বুর্সি ওয়ার্কলোড হ্যান্ডেল করা
অনিরূপ স্পাইকগুলোর জন্য, on-demand ক্যাপাসিটি বিস্ফোরণ সহ্য করতে পারে (সার্ভিস সীমার মধ্যে)। Provisioned মোডে auto scaling ব্যবহার করুন এবং ক্লায়েন্ট সাইডে থ্রটলের উপর exponential backoff with jitter প্রয়োগ করুন যাতে synchronized retries স্পাইক বাড়ান না।
স্কেলযোগ্য সিস্টেমের জন্য ডেটা মডেলিং প্যাটার্ন
DynamoDB ডেটা মডেলিংটি অ্যাক্সেস প্যাটার্ন থেকে শুরু হয়, ER ডায়াগ্রামের থেকে নয়। আপনি কীগুলিকে এমনভাবে ডিজাইন করেন যাতে প্রয়োজনীয় কুয়েরিগুলো দ্রুত Query অপারেশন হয়ে ওঠে, আর বাকি সবকিছু বাদ দেওয়া বা অ্যাসিঙ্ক্রোনাসভাবে হ্যান্ডল করা হয়।
সিঙ্গল-টেবিল ডিজাইন (আরও কেন দলগুলো পছন্দ করে)
“Single-table design” মানে এক টেবিলে একাধিক এন্টিটি টাইপ (user, order, message) সংরক্ষণ করে, এবং সামঞ্জস্যপূর্ণ কী কনভেনশনের মাধ্যমে সম্পর্কিত ডেটা একটি Query-এ আনা যায়। এটি ক্রস-এন্টিটি রাউন্ড-ট্রিপ কমায় এবং ল্যাটেন্সি পূর্বানুমানযোগ্য রাখে।
একটি কমন পদ্ধতি হলো কম্পোজিট কী:
PKলজিক্যাল পার্টিশন গ্রুপ করে (উদাহরণ:USER#123)SKঐ গ্রুপের আইটেমগুলোকে অর্ডার করে (উদাহরণ:PROFILE,ORDER#2025-12-01,MSG#000123)
এতে আপনি “কোনো ব্যবহারকারীর সবকিছু” বা “শুধু ব্যবহারকারীর অর্ডার” একটাই কুয়েরিতে আনতে পারেন sort-key প্রিফিক্স ব্যবহার করে।
সম্পর্ক: adjacency lists এবং many-to-many
গ্রাফ-মত সম্পর্কের জন্য, একটি adjacency list ভালো কাজ করে: এজগুলো আইটেম হিসেবে স্টোর করুন।
PK = USER#123,SK = FOLLOWS#USER#456
রিভার্স লুকআপ বা সত্যিকারের many-to-many সাপোর্ট করতে, একটি inverted edge আইটেম যোগ করুন অথবা প্রাসঙ্গিক রিড পাথের উপর ভিত্তি করে GSI-তে প্রজেক্ট করুন।
টাইম-সিরিজ: বকেট + sort key + TTL
ইভেন্ট ও মেট্রিকের জন্য, অনবদ্ধ পার্টিশন এড়াতে বকেট করুন:
PK = DEVICE#9#2025-12-22(ডিভাইস + দিন)SK = TS#1734825600(টাইমস্ট্যাম্প)
পেষ্টা করুন TTL ব্যবহার করে পুরনো পয়েন্টগুলো স্বয়ংক্রিয়ভাবে মুছে দিতে, এবং দ্রুত ড্যাশবোর্ডের জন্য আলাদা আইটেম হিসেবে অ্যাগ্রিগেট (ঘণ্টা/দৈনিক) রাখুন।
যদি আপনি কী কনভেনশনের উপর আরও গভীর রিফ্রেশ চান, দেখুন /blog/partition-key-and-sort-key-design।
Streams এবং ইভেন্ট-ড্রিভেন আর্কিটেকচার
DynamoDB Streams হলো DynamoDB-এর বিল্ট-ইন চেঞ্জ-ডাটা-ক্যাপচার (CDC) ফিড। টেবিলে এটি সক্রিয় করলে প্রতিটি insert, update, অথবা delete একটি স্ট্রিম রেকর্ড তৈরি করে যা ডাউনস্ট্রিম কনজিউমাররা পোল না করেই সাড়া দিতে পারে।
DynamoDB Streams মৌলিক বিষয়
একটি স্ট্রিম রেকর্ডে কীজ এবং (ঐচ্ছিকভাবে) আইটেমের পুরনো ও/অথবা নতুন ইমেজ থাকে, যেটা stream view type অনুযায়ী নির্ধারিত হয় (keys only, new image, old image, both)। রেকর্ডগুলো shards এ গ্রুপ করা থাকে, যেগুলোকে ধারাবাহিকভাবে পড়তে হয়।
ইভেন্ট-ড্রিভেন ওয়ার্কফ্লো নির্মাণ
কমন সেটআপ হলো DynamoDB Streams → AWS Lambda, যেখানে প্রতিটি রেকর্ড ব্যাচ একটি ফাংশন ট্রিগার করে। অন্যান্য কনজিউমারও ব্যবহার করা যায় (কাস্টম কনজিউমার, বা অ্যানালিটিক্স/লগিং সিস্টেমে পাইপ করা)।
টিপিক্যাল ওয়ার্কফ্লো:
- Materialized views: সোর্স টেবিল পরিবর্তনের সময় ডিনরমালাইজড রিড-মডেল টেবিলে লেখা।
- Cache invalidation: রাইটের পরে Redis/ElastiCache-এ আইটেম এক্সপায়ার বা রিফ্রেশ করা।
- Audit logs: পরিবর্তন ইভেন্টগুলো একটি অডিট টেবিল বা এক্সটার্নাল স্টোরে append করা।
এতে মূল টেবিলকে কম-ল্যাটেন্সি রিড/রাইটের জন্য অপ্টিমাইজ করা যায় এবং ডেরাইভড কাজগুলো অ্যাসিঙ্ক্রোনাস কনজিউমারে ঠেলে দেওয়া হয়।
অর্ডারিং, রিট্রাই, এবং সঠিকতা
Streams প্রতি শর্ডে অর্ডার করা প্রসেসিং সরবরাহ করে (যা সাধারণত partition key-এর সাথে কোরিলেট করে), কিন্তু সব কী-র উপর গ্লোবাল অর্ডার নেই। ডেলিভারি at-least-once, তাই ডুপ্লিকেট হতে পারে।
নিরাপদ হ্যান্ডলিংয়ের জন্য:
- হ্যান্ডলারগুলো idempotent রাখুন (উদাহরণ: key দিয়ে upsert, শর্তাধীন লেখা, বা প্রসেস করা ইভেন্ট আইডি সংরক্ষণ)
- রিট্রাই ও আংশিক ব্যাচ ব্যর্থতার প্রত্যাশা রাখুন; DLQ/অন-ফেলিয়ার ডেস্টিনেশন ব্যবহার করুন
- ই-মেল, পেমেন্টের মতো সাইড-এফেক্টগুলো ডিউপ্লিকেশন বা ট্রানজেকশনাল গার্ডের পিছনে রাখুন
এসব গ্যারান্টি মাথায় রেখে Streams DynamoDB-কে ইভেন্ট-ড্রিভেন সিস্টেমের জন্য শক্তিশালী বেস হিসেবে রূপান্তর করতে পারে।
নির্ভরযোগ্যতা, ব্যাকআপ, ও পর্যবেক্ষণ
DynamoDB উচ্চ উপলব্ধতার জন্য ডিজাইন করা হয়েছে—এটি একটি রিজিয়নের মধ্যে একাধিক Availability Zone জুড়ে ডেটা ছড়ায়। অধিকাংশ টিমের জন্য ব্যবহারিক নির্ভরযোগ্যতার জয়গুলো আসে একটি পরিষ্কার ব্যাকআপ কৌশল থাকা, রেপ্লিকেশন অপশন বোঝা, এবং সঠিক মেট্রিক পর্যবেক্ষণ করা থেকে।
ব্যাকআপ: অন-ডিমান্ড বনাম পয়েন্ট-ইন-টাইম রিকভারি
On-demand backups ম্যানুয়াল (বা অটোমেটেড) স্ন্যাপশট যা আপনি কোনো নির্দিষ্ট রিস্টোর পয়েন্ট নিতে চাইলে ব্যবহার করেন—মাইগ্রেশন করার আগে, রিলিজের পরে, বা বড় ব্যাকফিল করার আগে। এগুলো “বুকমার্ক” মুহূর্তের জন্য উপযুক্ত।
Point-in-time recovery (PITR) ক্রমাগত পরিবর্তন ক্যাপচার করে যাতে আপনি টেবিলকে রিস্টোর করতে পারেন রিটেনশন উইন্ডোর মধ্যে যেকোন সেকেন্ডে। PITR হল দুর্ঘটনাজনিত ডিলিট, বাজে ডিপ্লয়মেন্ট, বা ভুল লেখার বিরুদ্ধে নিরাপত্তা জাল।
রেপ্লিকেশন ও মাল্টি-রিজন অপশন
যদি মাল্টি-রিজন রেজিলিয়েন্স বা ব্যবহারকারীর কাছাকাছি কম-ল্যাটেন্সি রিড দরকার হয়, Global Tables নির্বাচিত রিজিয়নগুলোতে ডেটা রেপ্লিকেট করে। এগুলো ফেইলওভারের পরিকল্পনা সহজ করে, কিন্তু ক্রস-রিজন রেপ্লিকেশন ডিলে এবং কনফ্লিক্ট-রেজোলিউশনের বিষয়গুলো নিয়ে আসে—তাই লেখার প্যাটার্ন ও আইটেম মালিকানা পরিষ্কার রাখুন।
মনিটরিং অপরিহার্য
ন্যূনতম সতর্কতা দিন:
- রিড ও রাইটের ল্যাটেন্সি (p95/p99)
- থ্রটল হওয়া অনুরোধ ও সিস্টেম ত্রুটি
- কনসাম্ড ক্যাপাসিটি (এবং provisioned-এর তুলনায় হেডরুম)
এই সংকেতগুলো সাধারণত হট-পার্টিশন সমস্যা, অপর্যাপ্ত ক্যাপাসিটি, বা অপ্রত্যাশিত অ্যাক্সেস প্যাটার্নগুলো প্রকাশ করে।
ইনসিডেন্ট প্লেবুক
থ্রটলিং হলে প্রথমে কোন অ্যাক্সেস প্যাটার্ন এটা ঘটাচ্ছে তা শনাক্ত করুন, তারপর সাময়িকভাবে on-demand-এ সুইচ করা বা provisioned ক্যাপাসিটি বাড়ান, এবং হট কী শার্ডিং বিবেচনা করুন।
পার্শ্বিক আউটেজ বা ত্রুটি বাড়লে ব্লাস্ট রেডিয়াস কমান: অপ্রয়োজনীয় ট্র্যাফিক বন্ধ করুন, জিটারে ব্যাকঅফ দিয়ে রিট্রাই করুন, এবং টেবিল স্থিতিশীল না হওয়া পর্যন্ত গ্রেসফুলি ফেল ব্যাক (উদাহরণ: ক্যাশড রিড সার্ভ করা) করুন।
সিকিউরিটি ও অ্যাক্সেস কন্ট্রোল
DynamoDB সিকিউরিটি মূলত নির্ধারণ করে কারা কোন API অ্যাকশন কল করতে পারে, কোথা থেকে, এবং কোন কী-তে। কারণ টেবিলগুলো অনেক এন্টিটি টাইপ (এবং কখনো কখনো বহু টেন্যান্ট) ধারণ করে, অ্যাক্সেস কন্ট্রোলকে ডেটা মডেলের সাথে সঙ্গেই ডিজাইন করা উচিত।
IAM অনুমতিঃ ন্যূনতম অনুমতি
আইডেনটিটি-ভিত্তিক IAM পলিসি দিয়ে শুরু করুন যা অ্যাকশনগুলো (যেমন dynamodb:GetItem, Query, PutItem)কে সর্বনিম্ন সেটে সীমাবদ্ধ করে এবং নির্দিষ্ট টেবিল ARN-এ স্কোপ করে।
আরও সূক্ষ্ম নিয়ন্ত্রণের জন্য dynamodb:LeadingKeys ব্যবহার করুন যাতে partition key মান দ্বারা অ্যাক্সেস সীমাবদ্ধ করা যায়—উপযোগী যখন একটি সার্ভিস বা টেন্যান্ট শুধুমাত্র তার নিজস্ব কীস্পেসের আইটেমই পড়তে/লিখতে পারবে।
এনক্রিপশন: যাচাই করবার বিষয়
DynamoDB ডেটা অ্যাট-রেস্টে ডিফল্টভাবে AWS owned কী অথবা কাস্টমার-ম্যানেজড KMS কী ব্যবহার করে এনক্রিপ্ট করে। যদি আপনার কমপ্লায়েন্স প্রয়োজন থাকে, নিশ্চিত করুন:
- টেবিলটি উদ্দেশ্যমত KMS কী কনফিগার করা আছে
- কলিং রোলের কাছে প্রয়োজনীয় KMS অনুমতি রয়েছে (এবং অতিরিক্ত কিছু নয়)
ট্রানজিটে এনক্রিপশনের জন্য, ক্লায়েন্টরা HTTPS ব্যবহার করে তা নিশ্চিত করুন (AWS SDKs ডিফল্টভাবে করে)। যদি আপনি প্রক্সিতে TLS টার্মিনেট করেন, প্রক্সি এবং DynamoDB-এর মধ্যবর্তী হপ এখনও এনক্রিপ্টেড আছে কি না যাচাই করুন।
নেটওয়ার্ক কন্ট্রোল: ডেটা এক্সফিলট্রেশন পথ কমান
DynamoDB-এর জন্য VPC Gateway Endpoint ব্যবহার করুন যাতে ট্র্যাফিক AWS নেটওয়ার্কে থাকে এবং আপনি endpoint পলিসি প্রয়োগ করে অ্যাক্সেস সীমাবদ্ধ করতে পারেন। এটাকে egress কন্ট্রোল (NACLs, সিকিউরিটি গ্রুপ, রাউটিং) সাথে মিলিয়ে ব্যবহার করুন যাতে “সবকিছুই পাবলিক ইন্টারনেটে পৌঁছাতে পারে” এমন পথ এড়ানো যায়।
মাল্টি-টেন্যান্ট ডিজাইন ও আইসোলেশন প্যাটার্ন
শেয়ার্ড টেবিলের জন্য partition key-এ টেন্যান্ট শনাক্তকারী অন্তর্ভুক্ত করুন (উদাহরণ: TENANT#<id>), তারপর dynamodb:LeadingKeys-এর আইএএম কন্ডিশন দিয়ে টেন্যান্ট আইসোলেশন কার্যকর করুন।
যদি শক্তিশালী আইসোলেশন দরকার হয়, পৃথক টেবিল প্রতি টেন্যান্ট বা পরিবেশ বিবেচনা করুন; শেয়ার্ড টেবিল ডিশ-অপারেশনাল সরলতা ও খরচ দক্ষতার জন্য বরং উপযুক্ত যখন বিস্তৃত ব্লাস্ট-রেডিয়াস নিয়ন্ত্রণ খুব বেশি গুরুত্বপূর্ণ না।
খরচ অপ্টিমাইজেশন
DynamoDB প্রায়শই "নির্দিষ্ট হলে সস্তা, অস্পষ্ট হলে ব্যয়বহুল"। খরচ সাধারণত আপনার অ্যাক্সেস প্যাটার্ন অনুসরণ করে, তাই সেরা অপ্টিমাইজেশন কাজগুলো শুরু হয় সেই প্যাটার্নগুলোকে স্পষ্ট করে তুলেই।
খরচ চালকদের চেনা
আপনার বিল প্রধানত নির্ধারিত হবে:
- রিড ও রাইট (Provisioned মোডে RCUs/WCUs, On-Demand-এ অনুরোধ ইউনিট)
- স্টোরেজ (টেবিল ডেটা এবং আইটেম সাইজ)
- সেকেন্ডারি ইনডেক্স (প্রতিটি GSI-র নিজস্ব লেখা ও স্টোরেজ খরচ)
- Streams (স্ট্রীম রেকর্ডের বিরুদ্ধে রিড অনুরোধ এবং যেকোন ডাউনস্ট্রিম কনজিউমার)
একটি সাধারণ বিস্ময়: টেবিলে প্রতিটি রাইট একইসাথে প্রতিটি প্রভাবিত GSI-তেও একটি রাইট করে—তাই “আর একটু ইনডেক্স” লেখার খরচকে গুণ করতে পারে।
অপচয় এড়াতে কী ডিজাইন করুন
ভাল কী ডিজাইন ব্যয় কমায়। যদি আপনি প্রায়শই Scan-এর দিকে ঝুঁকছেন, আপনি এমন ডেটা পড়ছেন যা পরে বাদ দেয়া হয়—এটা খরচ বৃদ্ধি করে।
প্রাধান্য দিন:
- Query করুন partition key দ্বারা (এবং বিকল্পভাবে sort key শর্ত)
- GSI-তে সংকীর্ণ projections রাখুন (শুধুমাত্র অবশ্যই দরকারি অ্যাট্রিবিউটগুলো প্রজেক্ট করুন)
যদি কোনো অ্যাক্সেস প্যাটার্ন বিরল, তাহলে সেটি আলাদা টেবিল, একটি ETL কাজ, বা একটি ক্যাশড রিড-মডেল দিয়ে সার্ভ করা বিবেচনা করুন—স্থায়ী GSI হিসেবে রাখার বদলে।
TTL ও lifecycle দিয়ে স্টোরেজ নিয়ন্ত্রণ করুন
TTL ব্যবহার করে শোর্ট-লিভড আইটেম (সেশন, অস্থায়ী টোকেন, ইন্টারমিডিয়েট ওয়ার্কফ্লো স্টেট) স্বয়ংক্রিয়ভাবে মুছুন। এটি স্টোরেজ কমায় এবং ইনডেক্সকে ছোট রাখে।
অ্যাপেন্ড-হেভি ডেটার জন্য (ইভেন্ট, লগ), TTL এর সাথে এমন sort-key ডিজাইন মিলিয়ে রাখুন যাতে আপনি “শুধু রিসেন্ট” কুয়েরি করতে পারেন এবং সিস্টেমের পুরনো হিস্ট্রি ক্রমাগত টাচ না করে।
সঠিক আকারের ক্যাপাসিটি ও দুর্ঘটনাকালীন স্পাইক এড়ানো
Provisioned মোডে সংরক্ষণশীল বেসলাইন সেট করুন এবং বাস্তব মেট্রিকের উপর ভিত্তি করে auto scaling ব্যবহার করে স্কেল করুন। On-Demand মোডে, অদক্ষ প্যাটার্ন (বড় আইটেম, চ্যাটি ক্লায়েন্ট) যেগুলো রিকোয়েস্ট ভলিউম বাড়ায় সেগুলো লক্ষ করুন।
Scan-কে শেষ উপায় হিসেবে বিবেচনা করুন—যখন সত্যিই পূর্ণ-টেবিল প্রসেসিং দরকার, তখন এটাকে অফ-পিকে নির্ধারিত ব্যাচ হিসেবে চালান বা পেজিনেশন ও ব্যাকঅফ ব্যবহার করুন।
কখন DynamoDB নির্বাচন করবেন (এবং কখন নয়)
DynamoDB তখনই আলোকিত হয় যখন আপনার অ্যাপটি ভালভাবে কী-ভিত্তিক অ্যাক্সেস প্যাটার্ন হিসেবে প্রকাশ করা যায় এবং আপনাকে উচ্চ স্কেলে ধারাবাহিকভাবে কম ল্যাটেন্সি দরকার। যদি আপনি আপনার রিড ও রাইটগুলো আগেই (partition key, sort key, এবং কয়েকটি ইনডেক্স দ্বারা) বর্ণনা করতে পারেন, এটি প্রায়শই অত্যন্ত সহজ অপারেট করার উপায়।
যেখানে ভালো সুবিধা
DynamoDB একটি শক্তিশালী পছন্দ যখন আপনার কাছে:
- পূর্বানুমানযোগ্য কুয়েরি (ইউজার প্রোফাইল, ব্যবহারকারীর অর্ডার সময়ক্রমে, সেশন ID দ্বারা লোড)
- উচ্চ রাইট থ্রুপুট বা স্পাইকী ট্রাফিক যা আপনি মনিটর করতে চান না
- সার্ভার ব্যবস্থাপনা ছাড়াই হরিজন্টাল স্কেলিং দরকার
- Streams ব্যবহার করে ইভেন্ট-ড্রিভেন ডিজাইন
কখন বিকল্প বিবেচনা করবেন
অন্যদিকে বিবেচনা করুন যদি আপনার মূল চাহিদায় থাকে:
- অনেক এন্টিটির উপর জটিল জয়েন বা ঘন ঘন সম্পর্কগত ট্র্যাভার্সাল
- প্রতিটি সপ্তাহে বদলানো অন-দ্যা-ফ্লাই অন্বেষণাত্মক কুয়েরি ও অ্যানালিটিকস (group-by, ফিল্টারিং)
- না থাকলে বাহ্যিক ইনডেক্স ছাড়া ভারী টেক্সট সার্চ ও রিলেভেন্স র্যাঙ্কিং
হাইব্রিড পদ্ধতি যা ভালো কাজ করে
অনেক টিম DynamoDB রাখে “হট” অপারেশনাল রিড ও রাইটের জন্য, তারপর যোগ করে:
- অ্যানালিটিকস ও ইতিহাসের জন্য S3 + Athena
- ফুল-টেক্সট সার্চ ও ফেসেটিংয়ের জন্য OpenSearch (অথবা সমতুল্য)
- অত্যন্ত রিড-হেভি কী-এর জন্য একটি ক্যাশ লেয়ার
প্রোটোটাইপিং নোট: মডেল থেকে অ্যাপে পথটি সংক্ষিপ্ত করুন
যদি আপনি অ্যাক্সেস প্যাটার্ন এবং সিঙ্গল-টেবিল কনভেনশন যাচাই করছেন, ত্বরান্বিত উন্নতি গুরুত্বপূর্ণ। দলগুলো মাঝে মাঝে প্রোটোটাইপ করতে Koder.ai (একটি ভিব-কোডিং প্ল্যাটফর্ম যা চ্যাট থেকে ওয়েব, সার্ভার, এবং মোবাইল অ্যাপ তৈরি করে) ব্যবহার করে এবং বাস্তব কুয়েরি পথ বেরোলে DynamoDB কী ডিজাইন ইটারেট করে। প্রোডাকশনের ব্যাকএন্ড আলাদা হলেও, দ্রুত এন্ড-টু-এন্ড প্রোটোটাইপিং সাহায্য করে কোন কুয়েরিগুলো Query হওয়া উচিত এবং কোনগুলো দুর্ঘটনায় Scan হয়ে যায় তা উদ্ঘাটন করতে।
দ্রুত সিদ্ধান্ত চেকলিস্ট
যাচাই করুন: (1) আপনার শীর্ষ কুয়েরিগুলো কী-ভিত্তিক এবং পরিচিত, (2) সঠিকতার চাহিদা consistency মডেলের সাথে মেলে, (3) প্রত্যাশিত আইটেম সাইজ ও বৃদ্ধি বোঝা আছে, এবং (4) খরচ মডেল (on-demand বনাম provisioned ও autoscaling) আপনার বাজেটের সাথে মানায়।
সাধারণ প্রশ্ন
DynamoDB কী, এবং কখন এটি ভাল একটি পছন্দ?
DynamoDB হলো AWS-এর একটি ফুলি-ম্যানেজড NoSQL ডাটাবেস, যা উচ্চ মাত্রার স্কেলে ধারাবাহিকভাবে কম-ল্যাটেন্সির রিড/রাইট প্রদান করে। টিমগুলো এটি ব্যবহার করে যখন তারা কী-ভিত্তিক অ্যাক্সেস প্যাটার্ন (ID দিয়ে ফetch, মালিকভিত্তিক তালিকা, টাইম-রেঞ্জ কুয়েরি) নির্ধারণ করতে পারে এবং ডাটাবেস সার্ভার চালানোর ঝামেলা এড়াতে চায়।
এটি বিশেষভাবে উপযুক্ত মাইক্রোসার্ভিস, সার্ভারলেস অ্যাপ ও ইভেন্ট-ড্রিভেন সিস্টেমগুলোর জন্য।
DynamoDB-তে টেবিল, আইটেম, এবং অ্যাট্রিবিউট বলতে কী বোঝায়?
একটি টেবিল items (রোএর মত) ধারণ করে। প্রতিটি আইটেম বিভিন্ন বৈশিষ্ট্যের সেট—attributes (কলামের মত)—থাকে এবং এতে নেস্টেড ডাটা থাকতে পারে।
DynamoDB ভাল কাজ করে যখন একটি রিকোয়েস্ট সাধারণত “সম্পূর্ণ এন্টিটি” এনে দেয় কারণ আইটেমগুলোতে maps ও lists (JSON-সদৃশ কাঠামো) রাখা যায়।
সরল প্রাইমারি কী এবং কম্পোজিট প্রাইমারি কীর মধ্যে পার্থক্য কী?
কেবল একটি partition key থাকলে একটি আইটেম অনন্যভাবে শনাক্ত হয় (সিম্পল প্রাইমারি কী)। যখন partition key + sort key থাকে (কম্পোজিট কী), একই partition key শেয়ার করা কয়েকটি আইটেমকে আলাদা করে এবং sort key দ্বারা তাদের অর্ডার নির্ধারিত হয়।
কম্পোজিট কীগুলো এমন প্যাটার্ন সক্ষম করে:
- “একটি গ্রাহকের সকল অর্ডার”
- “একটি ডিভাইসের ইভেন্টসমূহ নির্দিষ্ট টাইমস্ট্যাম্পের মধ্যে”
কবে Query এবং কবে Scan ব্যবহার করা উচিত?
Query ব্যবহার করুন যখন আপনি partition key (এবং বিকল্পভাবে sort key শর্ত) নির্দিষ্ট করতে পারেন। এটা দ্রুত ও স্কেলেবল পথ।
Scan তখনই ব্যবহার করুন যখন সত্যিই সবকিছু পড়তে হবে; এটি পুরো টেবিল বা ইনডেক্স পড়ে এবং পরে ফিল্টার করে, তাই সাধারণত ধীর ও ব্যয়বহুল।
আপনি যদি খুবই ঘন ঘন Scan চালান, সেটা ইঙ্গিত করে আপনার কী বা ইনডেক্স ডিজাইন পরিবর্তন করা দরকার।
GSI ও LSI কি, এবং কিভাবে নির্বাচন করব?
সেকেন্ডারি ইনডেক্সগুলো alternate query path দেয়।
- GSI (Global Secondary Index): টেবিলের থেকে সম্পূর্ণ আলাদা partition key (ও বিকল্প sort key) থাকতে পারে; এটি পরে যোগ বা মুছা যায়।
- LSI (Local Secondary Index): মূল টেবিলের partition key শেয়ার করে কিন্তু আলাদা sort key ব্যবহার করে; এটি টেবিল তৈরির সময় সংজ্ঞায়িত করতে হয়।
ইনডেক্সগুলো লেখাকে বাড়িয়ে দেয় কারণ প্রতিটি ইনডেক্সেও লেখা হয়—এটা খরচ বাড়ায়।
On-Demand এবং Provisioned ক্যাপাসিটির মধ্যে কিভাবে নির্বাচন করব?
On-Demand বেছে নিন যদি ট্রাফিক অনিশ্চিত, স্পাইকী বা আপনি ক্যাপাসিটি পরিচালনা করতে না চান। আপনি রিকোয়েস্ট অনুযায়ী অর্থ প্রদান করবেন।
Provisioned বেছে নিন যদি ব্যবহার স্তিতিশীল/অনুমেয় এবং আপনি লাইফস্টাইলের খরচ নিয়ন্ত্রণ চান। এটাকে auto scaling-এ লাগানো যায়, তবে এটা হঠাৎ স্পাইকে ততক্ষণে রেসপন্ড নাও করতে পারে।
DynamoDB কী ধরনের consistency অপশন দেয়, এবং কখন এগুলো গুরুত্বপূর্ণ?
ডিফল্টভাবে রিডগুলো eventually consistent — অর্থাৎ লেখার পর সাময়িকভাবে পুরোনো মান দেখা যেতে পারে।
যদি পড়াটি অবশ্যই সর্বশেষ নিশ্চয়তা চায়, তখন strongly consistent রিড ব্যবহার করুন (একই রিজিয়নের বেস টেবিল থেকে)।
কনকারেন্সির মধ্যে সঠিকতার জন্য, সাধারণত ADD বা শর্তাধীন আপডেটের মতো অ্যাটমিক আপডেট ব্যবহার করা উত্তম।
কখন DynamoDB ট্রানজেকশন ব্যবহার করা উচিত?
Transactions (TransactWriteItems, TransactGetItems) ACID গ্যারান্টি দেয় পর্যন্ত ২৫টি আইটেম পর্যন্ত।
একসাথে একাধিক আইটেম আপডেট করতে (যেমন: অর্ডার তৈরি করা এবং ইনভেন্টরি রিজার্ভ করা) বা এমন ইনভারিয়েন্ট প্রতিষ্ঠা করতে যেগুলো আংশিক আপডেট সহ্য করতে পারে না—তখন ট্রানজেকশন ব্যবহার করুন।
তারা বেশি খরচ করে এবং ল্যাটেন্সি বাড়ায়, তাই শুধুমাত্র প্রয়োজনীয় ফ্লোতেই ব্যবহার করুন।
হট কী/পার্টিশন কী, এবং আমি কীভাবে তা এড়াব?
হট পার্টিশন ঘটে যখন খুব বেশি রিকোয়েস্ট একই partition key (বা কয়েকটি কনস্ট্যান্ট ভ্যালু) লক্ষ্য করে, ফলে টেবিলটি অন্যথায় নীরব্ধ থাকলেও থ্রটলিং দেখা দেয়।
সাধারণ প্রতিকার:
- উচ্চ-কার্ডিনালিটি partition key বেছে নিন
- Write sharding (ছোট র্যান্ডম/হ্যাশ সাফল বা প্রিফিক্স যোগ করা)
- টাইম-ব্যাকেট ব্যবহার করুন টাইম-সিরিজ ডেটার জন্য
- থ্রটল হলে exponential backoff with jitter ব্যবহার করুন
DynamoDB Streams কিভাবে ইভেন্ট-ড্রিভেন আর্কিটেকচারের সহায়ক?
DynamoDB Streams সক্রিয় করলে প্রতিটি insert, update, delete একটা স্ট্রিম রেকর্ড তৈরি করে। সাধারণ প্যাটার্ন হল Streams → Lambda যাতে প্রতিটি ব্যাচ রেকর্ড একটি ফাংশন ট্রিগার করে।
গুরুত্বপূর্ণ গ্যারান্টিগুলো:
- অর্ডারিং আছে প্রতি শর্ডে (গ্লোবাল অর্ডার নেই)
- ডেলিভারি at-least-once (ডুপ্লিকেট হতে পারে)
কনজিউমারগুলো অবশ্যই idempotent হওয়া উচিত (key দিয়ে upsert করা, শর্তাধীন লেখা, বা প্রসেস করা ইভেন্ট আইডি ট্র্যাক করা)।