আগের পর্বে R2 দিয়ে ফাইল স্টোরেজ শিখেছিলাম। এবার একদম ভিন্ন ধরনের একটা স্টোরেজ — KV (Key-Value)। এটা ছবি বা বড় ফাইলের জন্য না, বরং ছোট ছোট ডেটা — সেটিংস, ফ্ল্যাগ, ক্যাশড রেসপন্স — যা খুব দ্রুত পড়তে হয়, সারা বিশ্বের যেকোনো জায়গা থেকে।
KV কী এবং RTDB থেকে কীভাবে আলাদা
Firebase এর হাতেখড়ি সিরিজে আমরা RTDB শিখেছিলাম — রিয়েল-টাইম, জটিল query করা যায়, কিন্তু প্রতিটা read একটা নেটওয়ার্ক রাউন্ড-ট্রিপ। KV পুরোপুরি ভিন্ন দর্শনে বানানো — এটা eventually consistent (সাথে সাথে সব জায়গায় আপডেট নাও হতে পারে, কয়েক সেকেন্ড লাগতে পারে), কিন্তু বিনিময়ে read অস্বাভাবিক দ্রুত, কারণ ডেটা Cloudflare-এর গ্লোবাল নেটওয়ার্কের প্রতিটা লোকেশনে ক্যাশড থাকে।
KV vs RTDB — কখন কোনটা
| বিষয় | RTDB | KV |
|---|---|---|
| ডেটা আপডেট দেখা যায় | সাথে সাথে (রিয়েল-টাইম) | কিছু সেকেন্ড দেরি হতে পারে |
| Query ক্ষমতা | orderByChild, ফিল্টার | শুধু key দিয়ে সরাসরি খোঁজা |
| Read গতি | দ্রুত | অতি দ্রুত (এজ ক্যাশড) |
| সেরা ব্যবহার | লাইভ চ্যাট, ইউজার ডেটা, Todo | সেটিংস, ফিচার ফ্ল্যাগ, API রেসপন্স ক্যাশ |
সহজ নিয়ম — যদি ডেটা প্রায়ই বদলায় আর সাথে সাথে সবাইকে দেখাতে হয়, RTDB। যদি ডেটা কম বদলায় কিন্তু বারবার পড়তে হয় (আর দ্রুততম হতে হয়), KV।
Namespace তৈরি করা
KV-তে ডেটা রাখার জায়গাকে বলে Namespace — R2-এর bucket, বা RTDB-এর পুরো ডেটাবেজের মতোই একটা কনটেইনার।
wrangler kv namespace create "SITE_SETTINGS" # আউটপুটে একটা id পাওয়া যাবে, সেটা wrangler.toml-এ বসাতে হবে
# wrangler.toml name = "my-worker" main = "src/index.js" [[kv_namespaces]] binding = "SITE_SETTINGS" id = "abc123def456..." # wrangler kv namespace create থেকে পাওয়া id
ডেটা লেখা ও পড়া
R2-এর মতোই put() আর get(), কিন্তু এখানে ফাইলের বদলে টেক্সট/JSON।
export default {
async fetch(request, env, ctx) {
// লেখা
await env.SITE_SETTINGS.put("maintenance_mode", "false");
// পড়া
const value = await env.SITE_SETTINGS.get("maintenance_mode");
return new Response(`Maintenance mode: ${value}`);
},
};
JSON রাখতে চাইলে JSON.stringify/JSON.parse নিজে করতে হয় (Advanced JS-এর প্যাটার্ন), অথবা সরাসরি get(key, "json") ব্যবহার করা যায়।
// লেখা
await env.SITE_SETTINGS.put("homepage_config", JSON.stringify({
theme: "dark",
featuredBook: "অপরাজিত",
}));
// পড়া — সরাসরি অবজেক্ট হিসেবে
const config = await env.SITE_SETTINGS.get("homepage_config", "json");
console.log(config.theme); // "dark"
Expiration — নিজে থেকে মুছে যাওয়া ডেটা
KV-এর একটা শক্তিশালী ফিচার — একটা নির্দিষ্ট সময় পর ডেটা নিজে থেকেই মুছে যেতে পারে, ক্যাশিং-এর জন্য এটা খুবই কাজের।
// ৬০ সেকেন্ড পর নিজে থেকে মুছে যাবে
await env.SITE_SETTINGS.put("temp_token", "xyz123", {
expirationTtl: 60, // সেকেন্ডে
});
বাস্তব ব্যবহার — API রেসপন্স ক্যাশ করা
পর্ব ৬-এ আমরা Worker থেকে RTDB কল করেছিলাম। ধরা যাক /api/books-এ বারবার একই রিকোয়েস্ট আসছে — প্রতিবার RTDB-তে না গিয়ে, KV-তে কিছুক্ষণের জন্য ক্যাশ করে রাখা যায়।
export default {
async fetch(request, env, ctx) {
// প্রথমে ক্যাশ চেক করা
const cached = await env.SITE_SETTINGS.get("books_list", "json");
if (cached) {
return new Response(JSON.stringify(cached), {
headers: { "content-type": "application/json", "x-cache": "HIT" },
});
}
// ক্যাশে না থাকলে RTDB থেকে আনা
const res = await fetch("https://my-first-app-default-rtdb.firebasedatabase.app/books.json");
const books = await res.json();
// পরের বারের জন্য ৫ মিনিট ক্যাশ করে রাখা
await env.SITE_SETTINGS.put("books_list", JSON.stringify(books), { expirationTtl: 300 });
return new Response(JSON.stringify(books), {
headers: { "content-type": "application/json", "x-cache": "MISS" },
});
},
};
এই প্যাটার্নে প্রথম রিকোয়েস্টের পর পরবর্তী ৫ মিনিটে যত রিকোয়েস্টই আসুক, RTDB-তে না গিয়ে সরাসরি KV থেকে অতি দ্রুত রেসপন্স পাওয়া যাবে — RTDB-এর ওপর চাপ কমে, রেসপন্স টাইমও কমে।
ইন্টারেক্টিভ — Cache Hit/Miss সিমুলেশন
নিচে বারবার "রিকোয়েস্ট পাঠাও" চেপে দেখো প্রথমবার MISS (RTDB থেকে আনা), পরেরবারগুলো HIT (KV থেকে দ্রুত) কীভাবে দেখায়।
ভালো অভ্যাস
- KV-তে ঘন ঘন বদলানো ডেটা রাখবেন না — eventually consistent হওয়ায় সাথে সাথে সব জায়গায় নাও দেখাতে পারে; সেটার জন্য RTDB উপযুক্ত
- ক্যাশিং-এ সবসময় একটা যুক্তিসঙ্গত expirationTtl দিন — নাহলে পুরনো ডেটা অনির্দিষ্টকাল থেকে যেতে পারে
- সেনসিটিভ, ঘন ঘন-বদলানো ইউজার ডেটার জন্য KV না, RTDB বা D1 (পরের পর্ব) ব্যবহার করুন
নিজে চেষ্টা করো
Exercise:
- একটা KV namespace তৈরি করো, নিজের Worker-এ binding যোগ করো।
- একটা সেটিংস অবজেক্ট (যেমন থিম, ফিচার্ড কনটেন্ট) JSON আকারে KV-তে সেভ করো, তারপর ফিরে পেয়ে দেখো।
- উপরের ক্যাশিং প্যাটার্ন দিয়ে নিজের কোনো RTDB নোড ৫ মিনিটের জন্য ক্যাশ করে দেখো —
x-cacheহেডার চেক করে HIT/MISS যাচাই করো। expirationTtlদিয়ে একটা টেম্পোরারি ডেটা সেভ করো, কিছুক্ষণ পর সেটা সত্যিই মুছে গেছে কিনা চেক করো।
পরের পর্বে যা থাকছে
পরের পর্বে আমরা শিখব D1 পরিচিতি — Cloudflare-এর SQLite-ভিত্তিক ডেটাবেজ, যেখানে RTDB-এর JSON ট্রি-এর বদলে চেনা SQL টেবিল-স্টাইলে ডেটা রাখা যায়, আর কখন এটা RTDB/KV-এর চেয়ে ভালো পছন্দ।