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

অ্যামাজন DynamoDB হলো AWS-এর একটি ফুলি-ম্যানেজড NoSQL ডাটাবেস সার্ভিস, যা এমন অ্যাপলিকেশনগুলোর জন্য তৈরি করা হয়েছে যেগুলোকে প্রায় যে কোনো স্কেলে ধারাবাহিকভাবে কম ল্যাটেন্সির রিড ও রাইট দরকার। “ফুলি-ম্যানেজড” মানে AWS ইনফ্রাস্ট্রাকচার কাজগুলো—হার্ডওয়্যার প্রোভিশনিং, রেপ্লিকেশন, প্যাচিং, এবং অনেক অপারেশনাল কাজ—হ্যান্ডেল করে, যাতে দলগুলো ডাটাবেস সার্ভার চালানোর পরিবর্তে ফিচার ডেলিভারিতে ফোকাস করতে পারে।
মূলত DynamoDB ডেটা items (রো) হিসেবে tables-এ সঞ্চয় করে, কিন্তু প্রতিটি আইটেমে নমনীয় অ্যাট্রিবিউট থাকতে পারে। ডেটা মডেলটিকে নিম্নোক্তভাবে বুঝলে সুবিধা হয়:
দলগুলো DynamoDB বেছে নেয় যখন তারা পূর্বানুমানযোগ্য পারফরম্যান্স এবং সহজ অপারেশন চায় এমনও ওয়ার্কলোডের জন্য যা রিলেশনাল জয়েনে ঠিকভাবে ফিট করে না। এটা সাধারণত মাইক্রোসার্ভিস (প্রতিটি সার্ভিস তার নিজস্ব ডেটা মালিকানায় রাখে), সার্ভারলেস অ্যাপ যেখানে ট্রাফিক স্পাইক হয়, এবং এমন ইভেন্ট-ড্রিভেন সিস্টেমে ব্যবহৃত হয় যেগুলি ডেটার পরিবর্তনে প্রতিক্রিয়া করে।
এই পোস্টে টেবিল, কী, ইনডেক্স—এসব বিল্ডিং ব্লক, অ্যাক্সেস প্যাটার্ন অনুযায়ী মডেলিং (সিঙ্গল-টেবিল ডিজাইন সহ), স্কেলিং ও ক্যাপাসিটি মোড কিভাবে কাজ করে, এবং স্ট্রিমিং পরিবর্তনগুলো ইভেন্ট-ড্রিভেন আর্কিটেকচারে কিভাবে ব্যবহার করা যায়—এসব আলোচনা করা হবে।
DynamoDB কয়েকটি সহজ বিল্ডিং ব্লকের চারপাশে সংগঠিত, কিন্তু বিবরণগুলো গুরুত্বপূর্ণ কারণ সেগুলোই নির্ধারণ করে আপনি কীভাবে ডেটা মডেল করবেন এবং কোন অনুরোধগুলো কত দ্রুত (এবং খরচ-কার্যকরভাবে) চলে।
একটি টেবিল হলো টপ-লেভেল কনটেইনার। টেবিলের প্রতিটি রেকর্ড একটি আইটেম (রো-এর সমতুল্য), এবং প্রতিটি আইটেম হলো একটি সেট অ্যাট্রিবিউট (কলামের মত)।
রিলেশনাল ডাটাবেসের মতো নয়—একই টেবিলের আইটেমগুলোর একই অ্যাট্রিবিউট থাকা বাধ্যতামূলক নয়। একটি আইটেমে {status, total, customerId} থাকতে পারে, আর অন্যটিতে {status, shipmentTracking}—DynamoDB-তে ফিক্সড স্কিমা লাগে না।
প্রতিটি আইটেম অনন্যভাবে শনাক্ত হয় একটি প্রাইমারি কীর মাধ্যমে, এবং DynamoDB দুটি ধরনের সমর্থন করে:
প্র্যাকটিসে, কম্পোজিট কী “গ্রুপ করা” অ্যাক্সেস প্যাটার্ন যেমন “একই গ্রাহকের সব অর্ডার, নতুনতম প্রথম” এর সুবিধা দেয়।
Query আইটেম পড়ে প্রাইমারি কী (বা ইনডেক্স কী) দ্বারা। এটি একটি নির্দিষ্ট partition key লক্ষ্য করে এবং sort key রেঞ্জ দিয়ে ফিল্টার করতে পারে—এটাই দক্ষ এবং প্রেফার করা পথ।
Scan পুরো টেবিল (বা ইনডেক্স) ধরে হাঁটে এবং পরে ফিল্টার করে। শুরুতে সহজ, কিন্তু স্কেলে সাধারণত ধীর এবং ব্যয়বহুল।
কিছু কনস্ট্রেইন্ট আছে যা শুরুতেই অনুভব করবেন:
এই ভিত্তি গুলোই পরবর্তী অংশ—অ্যাক্সেস প্যাটার্ন, ইনডেক্সিং পছন্দ, এবং পারফরম্যান্স বৈশিষ্ট্য—নির্ধারণ করে।
DynamoDB প্রায়ই কেও-ভ্যালু স্টোর এবং ডকুমেন্ট ডাটাবেস উভয় হিসেবেই বর্ণনা করা হয়। এটা সঠিক, কিন্তু প্রতিদিনের ডিজাইনে প্রতিটির অর্থ কী তা বোঝা কাজে লাগে।
মূলত আপনি কী দিয়ে ডেটা রিটার্ন করেন। প্রাইমারি কী মান প্রদান করলে DynamoDB একটি একক আইটেম ফেরত দেয়। সেই কী-ভিত্তিক লুকআপই অনেক ওয়ার্কলোডে পূর্বানুমানযোগ্য, কম-ল্যাটেন্সি স্টোরেজ দেয়।
একই সাথে, একটি আইটেমে নেস্টেড অ্যাট্রিবিউট (maps ও lists) থাকতে পারে, যা এটিকে ডকুমেন্ট ডাটাবেসের মতো অনুভব করায়: আপনি স্ট্রিক্ট স্কিমা ছাড়াই স্ট্রাকচার্ড পে-লোড সংরক্ষণ করতে পারেন।
আইটেমগুলো স্বাভাবিকভাবেই JSON-সদৃশ ডেটার সাথে মানানসই:
profile.name, profile.address)।যখন একটি এন্টিটি সাধারণত পুরোটা পড়ে পাওয়া যায়—যেমন ইউজার প্রোফাইল, শপিং কার্ট, বা কনফিগারেশন বান্ডল—তখন এটি খুব ভাল ফিট করে।
DynamoDB সার্ভার-সাইড জয়েন সমর্থন করে না। যদি আপনার অ্যাপকে “একটি অর্ডার এবং তার লাইন আইটেম ও শিপিং স্ট্যাটাস” একবারে ফেরত দিতে হয়, আপনি প্রায়ই ডেনরমালাইজ করবেন: কিছু অ্যাট্রিবিউট কপিই করে বিভিন্ন আইটেমে রাখবেন, বা ছোট সাবস্ট্রাকচারগুলি সরাসরি একটি আইটেমে এমবেড করবেন।
ডেনরমালাইজেশন লেখার জটিলতা বাড়ায় এবং আপডেট ফ্যান-আউট তৈরি করতে পারে। বিনিময়ে আপনি কম রাউন্ড-ট্রিপ এবং দ্রুত রিড পান—প্রায়শই স্কেলযোগ্য সিস্টেমে এটাই গুরুত্বপূর্ণ।
সবচেয়ে দ্রুত DynamoDB কুয়েরিগুলো হলো যেগুলো আপনি “এই partition দিন” (এবং ঐ partition-ভিত্তিকভাবে “এই রেঞ্জ দিন”) এইভাবে প্রকাশ করতে পারেন। তাই কী চয়েস মূলত আপনি কিভাবে পড়বেন তা নিয়ে—শুধুমাত্র স্টোর করার উপায় নয়।
Partition key নির্ধারণ করে কোন ফিজিক্যাল পার্টিশনে একটি আইটেম সংরক্ষিত হবে। DynamoDB এই মানটি হ্যাশ করে ডেটা ও ট্রাফিক ছড়িয়ে দেয়। যদি অনেক অনুরোধ কয়েকটি partition key মানের উপর কেন্দ্রীভূত হয়, আপনি “হট” পার্টিশন তৈরি করবেন এবং থ্রুপুট সীমা পেরিয়ে যাবেন যদিও টেবিলটা মোটামুটিidle।
ভাল partition key:
"GLOBAL"-এর মতো কন্সট্যান্ট)Sort key থাকলে একই partition key শেয়ার করা আইটেমগুলো একসাথে রাখা হয় এবং sort key দ্বারা অর্ডার করা হয়। এটি দক্ষভাবে সক্ষম করে:
BETWEEN, begins_with)কমন প্যাটার্ন হলো sort key কম্পোজিট করা, যেমন TYPE#id বা TS#2025-12-22T10:00:00Z, যাতে একাধিক কুয়েরি শেপ সহায়ক হয় আলাদা টেবিল ছাড়া।
PK = USER#<id> (সরল GetItem)PK = USER#<id>, SK begins_with ORDER# (অথবা SK = CREATED_AT#...)PK = DEVICE#<id>, SK = TS#<timestamp> এবং BETWEEN দিয়ে টাইম উইন্ডোগুলিযদি আপনার partition key আপনার সর্বোচ্চ-ভলিউম কুয়েরিগুলোর সাথে মেলে এবং ভালোভাবে বিতরণ করে, আপনি ধারাবাহিকভাবে কম-ল্যাটেন্সির রিড ও রাইট পাবেন। যদি না করে, আপনি Scan, ফিল্টার, বা অতিরিক্ত ইনডেক্স দিয়ে ক্ষতিপূরণ করবেন—প্রতিটাই খরচ বাড়ায় এবং হট কীয়ের ঝুঁকি বাড়ায়।
সেকেন্ডারি ইনডেক্স DynamoDB-কে আপনার টেবিলের প্রাইমারি কী ছাড়াও বিকল্প কুয়েরি পথ দেয়। প্রতিবার যে নতুন অ্যাক্সেস প্যাটার্ন আসে তখন পুরো বেস টেবিল পরিবর্তন না করে, আপনি একটি ইনডেক্স যোগ করে একই আইটেমগুলোকে ভিন্ন কী দিয়ে কুয়েরি করতে পারবেন।
Global Secondary Index (GSI)-এর নিজস্ব partition key (এবং ঐচ্ছিক sort key) থাকে যা টেবিলটির থেকে সম্পূর্ণ আলাদা হতে পারে। এটা “গ্লোবাল” কারণ এটি সমস্ত টেবিল পার্টিশন জুড়ে বিস্তৃত এবং যেকোন সময় যোগ বা মুছে ফেলা যায়। নতুন অ্যাক্সেস প্যাটার্নের জন্য GSI ব্যবহার করুন যখন মূল কী ডিজাইনের সাথে তা মেলে না—উদাহরণ: টেবিল যদি orderId দ্বারা কিও করা থাকে কিন্তু আপনি customerId দ্বারা কুয়েরি করতে চান।
Local Secondary Index (LSI) বেস টেবিলের সাথে একই partition key শেয়ার করে কিন্তু আলাদা sort key ব্যবহার করে। LSI টেবিল তৈরির সময় সংজ্ঞায়িত করতে হয়। এগুলো তখন উপযোগী যখন আপনি একই এন্টিটি গ্রুপের মধ্যে একাধিক sort অর্ডার চান (যেমন গ্রাহকের অর্ডারগুলো createdAt বনাম status দ্বারা সাজানো করে পাওয়া)।
প্রজেকশন নির্ধারণ করে কোন অ্যাট্রিবিউটগুলো ইনডেক্সে রাখা হবে:
বেস টেবিলে প্রতিটি লেখা এক বা একাধিক ইনডেক্সে লেখাকে ট্রিগার করতে পারে। বেশি GSI এবং বড় প্রজেকশন লেখার খরচ ও ক্যাপাসিটি ব্যবহার বাড়ায়। স্থিতিশীল অ্যাক্সেস প্যাটার্ন অনুযায়ী ইনডেক্স পরিকল্পনা করুন, এবং সম্ভব হলে প্রজেক্ট হওয়া অ্যাট্রিবিউটগুলো ন্যূনতম রাখুন।
DynamoDB স্কেলিং শুরু হয় একটি পছন্দ দিয়ে: On-Demand বা Provisioned ক্যাপাসিটি। দুইই খুব উচ্চ থ্রুপুটে পৌঁছতে পারে, কিন্তু পরিবর্তনশীল ট্রাফিকে তারা আলাদা ভাবে আচরণ করে।
On-Demand সহজ: আপনি অনুরোধ ভিত্তিতে bezahlen করেন এবং DynamoDB স্বয়ংক্রিয়ভাবে পরিবর্তনশীল লোড সামলায়। এটি অনিয়মিত ট্রাফিক, প্রারম্ভিক পণ্যের জন্য, এবং স্পাইকী ওয়ার্কলোডের জন্য ভাল যেখানে আপনি ক্যাপাসিটি লক্ষ্য পরিচালনা করতে চান না।
Provisioned হল ক্যাপাসিটি পরিকল্পনা: আপনি রিড ও রাইট থ্রুপুট নির্দিষ্ট করেন (বা auto-scale করেন) এবং স্থিতিশীল প্রয়োগে আরও পূর্বানুমানযোগ্য মূল্যমান পান। এটি পরিচিত, স্থিতিশীল ওয়ার্কলোডের জন্য সাধারণত সস্তা।
Provisioned থ্রুপুট পরিমাপ করা হয়:
আপনার আইটেম সাইজ ও অ্যাক্সেস প্যাটার্ন বাস্তব খরচ নির্ধারণ করে: বড় আইটেম, স্ট্রং কনসিস্টেন্সি, এবং স্ক্যান দ্রুতই ক্যাপাসিটি পোড়াতে পারে।
Auto scaling ব্যবহারিকভাবে provisioned RCUs/WCUs-কে ইউটিলাইজেশন লক্ষ্য অনুযায়ী অ্যাডজাস্ট করে। এটি ধীর বৃদ্ধি বা পূর্বানুমানযোগ্য সাইকেলের জন্য সাহায্য করে, কিন্তু তা মুহূর্তে নয়। হঠাৎ স্পাইকে ক্যাপাসিটি যথেষ্ট দ্রুত না বাড়লে থ্রটলিং হওয়ার ফলে সমস্যা হতে পারে, এবং এটা হট পার্টিশন ঠিক করতে পারে না।
DynamoDB Accelerator (DAX) হলো একটি ইন-মেমরি ক্যাশ যা রিড ল্যাটেন্সি কমাতে এবং পুনরাবৃত্ত রিডগুলো অফলোড করতে পারে (উদাহরণ: জনপ্রিয় প্রোডাক্ট পেজ, সেশন লুকআপ, লিডারবোর্ড)। এটা বেশি উপকারী যখন অনেক ক্লায়েন্ট একই আইটেম বারবার চাই; এটি রাইট-হেভি প্যাটার্নে সহায়ক নয়, এবং ভালো কী ডিজাইনকে প্রতিস্থাপন করে না।
DynamoDB আপনাকে রিড গ্যারান্টি বনাম ল্যাটেন্সি ও খরচের মধ্যে ট্রেড-অফ করতে দেয়, তাই প্রতি অপারেশনের "সঠিকতা" কী তা স্পষ্ট করা গুরুত্বপূর্ণ।
ডিফল্টভাবে, GetItem ও Query eventually consistent রিড ব্যবহার করে: লেখার পরে সামান্য সময়ের জন্য পুরোনো মান দেখা যেতে পারে। এটি প্রায়শই ফিড, প্রোডাক্ট ক্যাটালগ, এবং অন্যান্য রিড-মোস্টলি ভিউগুলোর জন্য ঠিক থাকে।
Strongly consistent রিড (একটি অপশন, একই রিজিয়নের বেস টেবিল থেকে) গ্যারান্টি দেয় যে আপনি সর্বশেষ নিশ্চিত লেখাই দেখবেন। স্ট্রং কনসিস্টেন্সি বেশি রিড ক্যাপাসিটি খরচ করে এবং টেইল ল্যাটেন্সি বাড়াতে পারে, তাই শুধুমাত্র অত্যাবশ্যক রিডগুলোর জন্য ব্যবহার করুন।
Strong consistency দরকার হতে পারে এমন পরিস্থিতি:
কাউন্টারগুলোর জন্য, সবচেয়ে নিরাপদ পদ্ধতি সাধারণত “strong read then write” নয়, বরং অ্যাটমিক আপডেট (যেমন UpdateItem সাথে ADD) যাতে ইনক্রিমেন্ট হারিয়ে না যায়।
DynamoDB ট্রানজেকশন (TransactWriteItems, TransactGetItems) ACID সেমান্টিক্স প্রদান করে সর্বোচ্চ 25 আইটেম পর্যন্ত। এগুলো ব্যবহার করুন যখন আপনাকে একাধিক আইটেম একসঙ্গে আপডেট করতে হবে—যেমন অর্ডার লেখা এবং ইনভেন্টরি রিজার্ভ করা—অথবা এমন ইনভারিয়েন্ট যা আংশিক স্টেটে সহ্য করতে পারে না।
রিট্রাইগুলি ডিসট্রিবিউটেড সিস্টেমে স্বাভাবিক। লিখাগুলো idempotent করুন যাতে রিট্রাই ডুপ্লিকেট এফেক্ট তৈরি না করে:
ConditionExpression দিয়ে অনন্যতা নিশ্চিত করুন (যেমন attribute_not_exists)\n- রিড-Modify-রাইট লুপের পরিবর্তে অ্যাটমিক আপডেট প্রাধান্য দিনDynamoDB-এ সঠিকতা মূলত সঠিক consistency লেভেল বাছাই এবং এমন অপারেশন ডিজাইন করার উপর নির্ভর করে যাতে রিট্রাই ডেটা ভঙ্গ করে না।
DynamoDB টেবিলের ডেটা একাধিক ফিজিক্যাল পার্টিশনে সংরক্ষণ করে। প্রতিটি পার্টিশনের পড়া/লেখার জন্য সীমিত থ্রুপুট এবং কতটা ডেটা রাখা যাবে তার সীমা আছে। আপনার partition key নির্ধারণ করে আইটেম কোথায় থাকে; যদি খুব বেশি অনুরোধ একই partition key (বা কয়েকটি মান) লক্ষ্য করে, সেই পার্টিশনই বটলনেক হয়ে যাবে।
হট পার্টিশন সাধারণত কী-বেছে নেয়ার কারণে ঘটে: একটি “গ্লোবাল” partition key যেমন USER#1, TENANT#default, বা STATUS#OPEN, অথবা টাইম-অর্ডারড প্যাটার্ন যেখানে সবাই একটিভ “এখন” লেখে এক partition এ।
সাধারণত আপনি দেখতে পাবেন:
ProvisionedThroughputExceededException)প্রথমে বিতরণের জন্য ডিজাইন করুন, পরে কুয়েরি সুবিধার্থে:
TENANT#<id> কনস্ট্যান্টের বদলে)ORDER#<id>#<shard> যাতে N শার্ডে লেখা ছড়ায়, এবং প্রয়োজন হলে শার্ড জুড়ে কুয়েরি করুন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 list ভালো কাজ করে: এজগুলো আইটেম হিসেবে স্টোর করুন।
PK = USER#123, SK = FOLLOWS#USER#456রিভার্স লুকআপ বা সত্যিকারের many-to-many সাপোর্ট করতে, একটি inverted edge আইটেম যোগ করুন অথবা প্রাসঙ্গিক রিড পাথের উপর ভিত্তি করে GSI-তে প্রজেক্ট করুন।
ইভেন্ট ও মেট্রিকের জন্য, অনবদ্ধ পার্টিশন এড়াতে বকেট করুন:
PK = DEVICE#9#2025-12-22 (ডিভাইস + দিন)SK = TS#1734825600 (টাইমস্ট্যাম্প)পেষ্টা করুন TTL ব্যবহার করে পুরনো পয়েন্টগুলো স্বয়ংক্রিয়ভাবে মুছে দিতে, এবং দ্রুত ড্যাশবোর্ডের জন্য আলাদা আইটেম হিসেবে অ্যাগ্রিগেট (ঘণ্টা/দৈনিক) রাখুন।
যদি আপনি কী কনভেনশনের উপর আরও গভীর রিফ্রেশ চান, দেখুন /blog/partition-key-and-sort-key-design।
DynamoDB Streams হলো DynamoDB-এর বিল্ট-ইন চেঞ্জ-ডাটা-ক্যাপচার (CDC) ফিড। টেবিলে এটি সক্রিয় করলে প্রতিটি insert, update, অথবা delete একটি স্ট্রিম রেকর্ড তৈরি করে যা ডাউনস্ট্রিম কনজিউমাররা পোল না করেই সাড়া দিতে পারে।
একটি স্ট্রিম রেকর্ডে কীজ এবং (ঐচ্ছিকভাবে) আইটেমের পুরনো ও/অথবা নতুন ইমেজ থাকে, যেটা stream view type অনুযায়ী নির্ধারিত হয় (keys only, new image, old image, both)। রেকর্ডগুলো shards এ গ্রুপ করা থাকে, যেগুলোকে ধারাবাহিকভাবে পড়তে হয়।
কমন সেটআপ হলো DynamoDB Streams → AWS Lambda, যেখানে প্রতিটি রেকর্ড ব্যাচ একটি ফাংশন ট্রিগার করে। অন্যান্য কনজিউমারও ব্যবহার করা যায় (কাস্টম কনজিউমার, বা অ্যানালিটিক্স/লগিং সিস্টেমে পাইপ করা)।
টিপিক্যাল ওয়ার্কফ্লো:
এতে মূল টেবিলকে কম-ল্যাটেন্সি রিড/রাইটের জন্য অপ্টিমাইজ করা যায় এবং ডেরাইভড কাজগুলো অ্যাসিঙ্ক্রোনাস কনজিউমারে ঠেলে দেওয়া হয়।
Streams প্রতি শর্ডে অর্ডার করা প্রসেসিং সরবরাহ করে (যা সাধারণত partition key-এর সাথে কোরিলেট করে), কিন্তু সব কী-র উপর গ্লোবাল অর্ডার নেই। ডেলিভারি at-least-once, তাই ডুপ্লিকেট হতে পারে।
নিরাপদ হ্যান্ডলিংয়ের জন্য:
এসব গ্যারান্টি মাথায় রেখে Streams DynamoDB-কে ইভেন্ট-ড্রিভেন সিস্টেমের জন্য শক্তিশালী বেস হিসেবে রূপান্তর করতে পারে।
DynamoDB উচ্চ উপলব্ধতার জন্য ডিজাইন করা হয়েছে—এটি একটি রিজিয়নের মধ্যে একাধিক Availability Zone জুড়ে ডেটা ছড়ায়। অধিকাংশ টিমের জন্য ব্যবহারিক নির্ভরযোগ্যতার জয়গুলো আসে একটি পরিষ্কার ব্যাকআপ কৌশল থাকা, রেপ্লিকেশন অপশন বোঝা, এবং সঠিক মেট্রিক পর্যবেক্ষণ করা থেকে।
On-demand backups ম্যানুয়াল (বা অটোমেটেড) স্ন্যাপশট যা আপনি কোনো নির্দিষ্ট রিস্টোর পয়েন্ট নিতে চাইলে ব্যবহার করেন—মাইগ্রেশন করার আগে, রিলিজের পরে, বা বড় ব্যাকফিল করার আগে। এগুলো “বুকমার্ক” মুহূর্তের জন্য উপযুক্ত।
Point-in-time recovery (PITR) ক্রমাগত পরিবর্তন ক্যাপচার করে যাতে আপনি টেবিলকে রিস্টোর করতে পারেন রিটেনশন উইন্ডোর মধ্যে যেকোন সেকেন্ডে। PITR হল দুর্ঘটনাজনিত ডিলিট, বাজে ডিপ্লয়মেন্ট, বা ভুল লেখার বিরুদ্ধে নিরাপত্তা জাল।
যদি মাল্টি-রিজন রেজিলিয়েন্স বা ব্যবহারকারীর কাছাকাছি কম-ল্যাটেন্সি রিড দরকার হয়, Global Tables নির্বাচিত রিজিয়নগুলোতে ডেটা রেপ্লিকেট করে। এগুলো ফেইলওভারের পরিকল্পনা সহজ করে, কিন্তু ক্রস-রিজন রেপ্লিকেশন ডিলে এবং কনফ্লিক্ট-রেজোলিউশনের বিষয়গুলো নিয়ে আসে—তাই লেখার প্যাটার্ন ও আইটেম মালিকানা পরিষ্কার রাখুন।
ন্যূনতম সতর্কতা দিন:
এই সংকেতগুলো সাধারণত হট-পার্টিশন সমস্যা, অপর্যাপ্ত ক্যাপাসিটি, বা অপ্রত্যাশিত অ্যাক্সেস প্যাটার্নগুলো প্রকাশ করে।
থ্রটলিং হলে প্রথমে কোন অ্যাক্সেস প্যাটার্ন এটা ঘটাচ্ছে তা শনাক্ত করুন, তারপর সাময়িকভাবে on-demand-এ সুইচ করা বা provisioned ক্যাপাসিটি বাড়ান, এবং হট কী শার্ডিং বিবেচনা করুন।
পার্শ্বিক আউটেজ বা ত্রুটি বাড়লে ব্লাস্ট রেডিয়াস কমান: অপ্রয়োজনীয় ট্র্যাফিক বন্ধ করুন, জিটারে ব্যাকঅফ দিয়ে রিট্রাই করুন, এবং টেবিল স্থিতিশীল না হওয়া পর্যন্ত গ্রেসফুলি ফেল ব্যাক (উদাহরণ: ক্যাশড রিড সার্ভ করা) করুন।
DynamoDB সিকিউরিটি মূলত নির্ধারণ করে কারা কোন API অ্যাকশন কল করতে পারে, কোথা থেকে, এবং কোন কী-তে। কারণ টেবিলগুলো অনেক এন্টিটি টাইপ (এবং কখনো কখনো বহু টেন্যান্ট) ধারণ করে, অ্যাক্সেস কন্ট্রোলকে ডেটা মডেলের সাথে সঙ্গেই ডিজাইন করা উচিত।
আইডেনটিটি-ভিত্তিক IAM পলিসি দিয়ে শুরু করুন যা অ্যাকশনগুলো (যেমন dynamodb:GetItem, Query, PutItem)কে সর্বনিম্ন সেটে সীমাবদ্ধ করে এবং নির্দিষ্ট টেবিল ARN-এ স্কোপ করে।
আরও সূক্ষ্ম নিয়ন্ত্রণের জন্য dynamodb:LeadingKeys ব্যবহার করুন যাতে partition key মান দ্বারা অ্যাক্সেস সীমাবদ্ধ করা যায়—উপযোগী যখন একটি সার্ভিস বা টেন্যান্ট শুধুমাত্র তার নিজস্ব কীস্পেসের আইটেমই পড়তে/লিখতে পারবে।
DynamoDB ডেটা অ্যাট-রেস্টে ডিফল্টভাবে AWS owned কী অথবা কাস্টমার-ম্যানেজড KMS কী ব্যবহার করে এনক্রিপ্ট করে। যদি আপনার কমপ্লায়েন্স প্রয়োজন থাকে, নিশ্চিত করুন:
ট্রানজিটে এনক্রিপশনের জন্য, ক্লায়েন্টরা HTTPS ব্যবহার করে তা নিশ্চিত করুন (AWS SDKs ডিফল্টভাবে করে)। যদি আপনি প্রক্সিতে TLS টার্মিনেট করেন, প্রক্সি এবং DynamoDB-এর মধ্যবর্তী হপ এখনও এনক্রিপ্টেড আছে কি না যাচাই করুন।
DynamoDB-এর জন্য VPC Gateway Endpoint ব্যবহার করুন যাতে ট্র্যাফিক AWS নেটওয়ার্কে থাকে এবং আপনি endpoint পলিসি প্রয়োগ করে অ্যাক্সেস সীমাবদ্ধ করতে পারেন। এটাকে egress কন্ট্রোল (NACLs, সিকিউরিটি গ্রুপ, রাউটিং) সাথে মিলিয়ে ব্যবহার করুন যাতে “সবকিছুই পাবলিক ইন্টারনেটে পৌঁছাতে পারে” এমন পথ এড়ানো যায়।
শেয়ার্ড টেবিলের জন্য partition key-এ টেন্যান্ট শনাক্তকারী অন্তর্ভুক্ত করুন (উদাহরণ: TENANT#<id>), তারপর dynamodb:LeadingKeys-এর আইএএম কন্ডিশন দিয়ে টেন্যান্ট আইসোলেশন কার্যকর করুন।
যদি শক্তিশালী আইসোলেশন দরকার হয়, পৃথক টেবিল প্রতি টেন্যান্ট বা পরিবেশ বিবেচনা করুন; শেয়ার্ড টেবিল ডিশ-অপারেশনাল সরলতা ও খরচ দক্ষতার জন্য বরং উপযুক্ত যখন বিস্তৃত ব্লাস্ট-রেডিয়াস নিয়ন্ত্রণ খুব বেশি গুরুত্বপূর্ণ না।
DynamoDB প্রায়শই "নির্দিষ্ট হলে সস্তা, অস্পষ্ট হলে ব্যয়বহুল"। খরচ সাধারণত আপনার অ্যাক্সেস প্যাটার্ন অনুসরণ করে, তাই সেরা অপ্টিমাইজেশন কাজগুলো শুরু হয় সেই প্যাটার্নগুলোকে স্পষ্ট করে তুলেই।
আপনার বিল প্রধানত নির্ধারিত হবে:
একটি সাধারণ বিস্ময়: টেবিলে প্রতিটি রাইট একইসাথে প্রতিটি প্রভাবিত GSI-তেও একটি রাইট করে—তাই “আর একটু ইনডেক্স” লেখার খরচকে গুণ করতে পারে।
ভাল কী ডিজাইন ব্যয় কমায়। যদি আপনি প্রায়শই Scan-এর দিকে ঝুঁকছেন, আপনি এমন ডেটা পড়ছেন যা পরে বাদ দেয়া হয়—এটা খরচ বৃদ্ধি করে।
প্রাধান্য দিন:
যদি কোনো অ্যাক্সেস প্যাটার্ন বিরল, তাহলে সেটি আলাদা টেবিল, একটি ETL কাজ, বা একটি ক্যাশড রিড-মডেল দিয়ে সার্ভ করা বিবেচনা করুন—স্থায়ী GSI হিসেবে রাখার বদলে।
TTL ব্যবহার করে শোর্ট-লিভড আইটেম (সেশন, অস্থায়ী টোকেন, ইন্টারমিডিয়েট ওয়ার্কফ্লো স্টেট) স্বয়ংক্রিয়ভাবে মুছুন। এটি স্টোরেজ কমায় এবং ইনডেক্সকে ছোট রাখে।
অ্যাপেন্ড-হেভি ডেটার জন্য (ইভেন্ট, লগ), TTL এর সাথে এমন sort-key ডিজাইন মিলিয়ে রাখুন যাতে আপনি “শুধু রিসেন্ট” কুয়েরি করতে পারেন এবং সিস্টেমের পুরনো হিস্ট্রি ক্রমাগত টাচ না করে।
Provisioned মোডে সংরক্ষণশীল বেসলাইন সেট করুন এবং বাস্তব মেট্রিকের উপর ভিত্তি করে auto scaling ব্যবহার করে স্কেল করুন। On-Demand মোডে, অদক্ষ প্যাটার্ন (বড় আইটেম, চ্যাটি ক্লায়েন্ট) যেগুলো রিকোয়েস্ট ভলিউম বাড়ায় সেগুলো লক্ষ করুন।
Scan-কে শেষ উপায় হিসেবে বিবেচনা করুন—যখন সত্যিই পূর্ণ-টেবিল প্রসেসিং দরকার, তখন এটাকে অফ-পিকে নির্ধারিত ব্যাচ হিসেবে চালান বা পেজিনেশন ও ব্যাকঅফ ব্যবহার করুন।
DynamoDB তখনই আলোকিত হয় যখন আপনার অ্যাপটি ভালভাবে কী-ভিত্তিক অ্যাক্সেস প্যাটার্ন হিসেবে প্রকাশ করা যায় এবং আপনাকে উচ্চ স্কেলে ধারাবাহিকভাবে কম ল্যাটেন্সি দরকার। যদি আপনি আপনার রিড ও রাইটগুলো আগেই (partition key, sort key, এবং কয়েকটি ইনডেক্স দ্বারা) বর্ণনা করতে পারেন, এটি প্রায়শই অত্যন্ত সহজ অপারেট করার উপায়।
DynamoDB একটি শক্তিশালী পছন্দ যখন আপনার কাছে:
অন্যদিকে বিবেচনা করুন যদি আপনার মূল চাহিদায় থাকে:
অনেক টিম DynamoDB রাখে “হট” অপারেশনাল রিড ও রাইটের জন্য, তারপর যোগ করে:
যদি আপনি অ্যাক্সেস প্যাটার্ন এবং সিঙ্গল-টেবিল কনভেনশন যাচাই করছেন, ত্বরান্বিত উন্নতি গুরুত্বপূর্ণ। দলগুলো মাঝে মাঝে প্রোটোটাইপ করতে Koder.ai (একটি ভিব-কোডিং প্ল্যাটফর্ম যা চ্যাট থেকে ওয়েব, সার্ভার, এবং মোবাইল অ্যাপ তৈরি করে) ব্যবহার করে এবং বাস্তব কুয়েরি পথ বেরোলে DynamoDB কী ডিজাইন ইটারেট করে। প্রোডাকশনের ব্যাকএন্ড আলাদা হলেও, দ্রুত এন্ড-টু-এন্ড প্রোটোটাইপিং সাহায্য করে কোন কুয়েরিগুলো Query হওয়া উচিত এবং কোনগুলো দুর্ঘটনায় Scan হয়ে যায় তা উদ্ঘাটন করতে।
যাচাই করুন: (1) আপনার শীর্ষ কুয়েরিগুলো কী-ভিত্তিক এবং পরিচিত, (2) সঠিকতার চাহিদা consistency মডেলের সাথে মেলে, (3) প্রত্যাশিত আইটেম সাইজ ও বৃদ্ধি বোঝা আছে, এবং (4) খরচ মডেল (on-demand বনাম provisioned ও autoscaling) আপনার বাজেটের সাথে মানায়।
DynamoDB হলো AWS-এর একটি ফুলি-ম্যানেজড NoSQL ডাটাবেস, যা উচ্চ মাত্রার স্কেলে ধারাবাহিকভাবে কম-ল্যাটেন্সির রিড/রাইট প্রদান করে। টিমগুলো এটি ব্যবহার করে যখন তারা কী-ভিত্তিক অ্যাক্সেস প্যাটার্ন (ID দিয়ে ফetch, মালিকভিত্তিক তালিকা, টাইম-রেঞ্জ কুয়েরি) নির্ধারণ করতে পারে এবং ডাটাবেস সার্ভার চালানোর ঝামেলা এড়াতে চায়।
এটি বিশেষভাবে উপযুক্ত মাইক্রোসার্ভিস, সার্ভারলেস অ্যাপ ও ইভেন্ট-ড্রিভেন সিস্টেমগুলোর জন্য।
একটি টেবিল items (রোএর মত) ধারণ করে। প্রতিটি আইটেম বিভিন্ন বৈশিষ্ট্যের সেট—attributes (কলামের মত)—থাকে এবং এতে নেস্টেড ডাটা থাকতে পারে।
DynamoDB ভাল কাজ করে যখন একটি রিকোয়েস্ট সাধারণত “সম্পূর্ণ এন্টিটি” এনে দেয় কারণ আইটেমগুলোতে maps ও lists (JSON-সদৃশ কাঠামো) রাখা যায়।
কেবল একটি partition key থাকলে একটি আইটেম অনন্যভাবে শনাক্ত হয় (সিম্পল প্রাইমারি কী)। যখন partition key + sort key থাকে (কম্পোজিট কী), একই partition key শেয়ার করা কয়েকটি আইটেমকে আলাদা করে এবং sort key দ্বারা তাদের অর্ডার নির্ধারিত হয়।
কম্পোজিট কীগুলো এমন প্যাটার্ন সক্ষম করে:
Query ব্যবহার করুন যখন আপনি partition key (এবং বিকল্পভাবে sort key শর্ত) নির্দিষ্ট করতে পারেন। এটা দ্রুত ও স্কেলেবল পথ।
Scan তখনই ব্যবহার করুন যখন সত্যিই সবকিছু পড়তে হবে; এটি পুরো টেবিল বা ইনডেক্স পড়ে এবং পরে ফিল্টার করে, তাই সাধারণত ধীর ও ব্যয়বহুল।
আপনি যদি খুবই ঘন ঘন Scan চালান, সেটা ইঙ্গিত করে আপনার কী বা ইনডেক্স ডিজাইন পরিবর্তন করা দরকার।
সেকেন্ডারি ইনডেক্সগুলো alternate query path দেয়।
ইনডেক্সগুলো লেখাকে বাড়িয়ে দেয় কারণ প্রতিটি ইনডেক্সেও লেখা হয়—এটা খরচ বাড়ায়।
On-Demand বেছে নিন যদি ট্রাফিক অনিশ্চিত, স্পাইকী বা আপনি ক্যাপাসিটি পরিচালনা করতে না চান। আপনি রিকোয়েস্ট অনুযায়ী অর্থ প্রদান করবেন।
Provisioned বেছে নিন যদি ব্যবহার স্তিতিশীল/অনুমেয় এবং আপনি লাইফস্টাইলের খরচ নিয়ন্ত্রণ চান। এটাকে auto scaling-এ লাগানো যায়, তবে এটা হঠাৎ স্পাইকে ততক্ষণে রেসপন্ড নাও করতে পারে।
ডিফল্টভাবে রিডগুলো eventually consistent — অর্থাৎ লেখার পর সাময়িকভাবে পুরোনো মান দেখা যেতে পারে।
যদি পড়াটি অবশ্যই সর্বশেষ নিশ্চয়তা চায়, তখন strongly consistent রিড ব্যবহার করুন (একই রিজিয়নের বেস টেবিল থেকে)।
কনকারেন্সির মধ্যে সঠিকতার জন্য, সাধারণত ADD বা শর্তাধীন আপডেটের মতো অ্যাটমিক আপডেট ব্যবহার করা উত্তম।
Transactions (TransactWriteItems, TransactGetItems) ACID গ্যারান্টি দেয় পর্যন্ত ২৫টি আইটেম পর্যন্ত।
একসাথে একাধিক আইটেম আপডেট করতে (যেমন: অর্ডার তৈরি করা এবং ইনভেন্টরি রিজার্ভ করা) বা এমন ইনভারিয়েন্ট প্রতিষ্ঠা করতে যেগুলো আংশিক আপডেট সহ্য করতে পারে না—তখন ট্রানজেকশন ব্যবহার করুন।
তারা বেশি খরচ করে এবং ল্যাটেন্সি বাড়ায়, তাই শুধুমাত্র প্রয়োজনীয় ফ্লোতেই ব্যবহার করুন।
হট পার্টিশন ঘটে যখন খুব বেশি রিকোয়েস্ট একই partition key (বা কয়েকটি কনস্ট্যান্ট ভ্যালু) লক্ষ্য করে, ফলে টেবিলটি অন্যথায় নীরব্ধ থাকলেও থ্রটলিং দেখা দেয়।
সাধারণ প্রতিকার:
DynamoDB Streams সক্রিয় করলে প্রতিটি insert, update, delete একটা স্ট্রিম রেকর্ড তৈরি করে। সাধারণ প্যাটার্ন হল Streams → Lambda যাতে প্রতিটি ব্যাচ রেকর্ড একটি ফাংশন ট্রিগার করে।
গুরুত্বপূর্ণ গ্যারান্টিগুলো:
কনজিউমারগুলো অবশ্যই হওয়া উচিত (key দিয়ে upsert করা, শর্তাধীন লেখা, বা প্রসেস করা ইভেন্ট আইডি ট্র্যাক করা)।