কিছুক্ষণ আগে, আমরা ড্রিজল ORM-এর সাথে সহযোগিতা করার সুযোগ পেয়েছি৷
৷এই TypeScript ORM-কে সম্প্রদায়ের কাছে কীভাবে পছন্দ করা হয়েছে তা দেখে, আমাদের "হ্যাঁ 😳" বলার সিদ্ধান্তটি ছিল অমনোযোগী:

এই নিবন্ধে, আমরা দেখব কিভাবে আমাদের Upstash Redis x Drizzle ক্যাশিং ইন্টিগ্রেশন SQL কর্মক্ষমতা উন্নত করে এবং কিভাবে আমরা Lua স্ক্রিপ্ট এবং হ্যাশ ডেটা স্ট্রাকচার ব্যবহার করেছি ইন্টিগ্রেশন অপ্টিমাইজ করতে।
চ্যালেঞ্জ:এসকিউএল পারফরম্যান্স ইন মডার্ন অ্যাপ্লিকেশন
ঐতিহ্যগত SQL ডাটাবেসগুলি সামঞ্জস্যপূর্ণ এবং জটিল সম্পর্কের মডেলিংয়ে দুর্দান্ত, কিন্তু তারা এর সাথে লড়াই করতে পারে:
- উচ্চ বিলম্ব বিতরণ করা পরিবেশে
- সংযোগ পুলিং সীমাবদ্ধতা সার্ভারহীন ফাংশনে
- পুনরাবৃত্ত প্রশ্ন ওভারহেড প্রায়শই অ্যাক্সেস করা ডেটার জন্য
- স্কেল করার বাধা ভারী পড়ার লোডের অধীনে
সমাধান? একটি ক্যাশিং স্তর যা আপনার ডেটা সম্পর্ক বুঝতে পারে এবং স্বয়ংক্রিয়ভাবে ক্যাশে অবৈধকরণ পরিচালনা করে৷
৷Upstash x ড্রিজল ক্যাশিং কিভাবে কাজ করে
পঠন কর্মক্ষমতা উন্নত করা:ক্যাশে-ফার্স্ট ফলব্যাক সহ
যখন আপনি ড্রিজল ক্যাশিং সক্ষম করে একটি ক্যোয়ারী চালান, তখন আমাদের ইন্টিগ্রেশন প্রথমে একটি ক্যাশে ফলাফলের জন্য Redis চেক করে:
- ক্যাশে মিস৷ :যদি না পাওয়া যায়, প্রশ্নটি আপনার ডাটাবেস থেকে পড়ে। ফলাফল নির্ভরশীল টেবিল সম্পর্কে মেটাডেটা সহ Redis এ সংরক্ষণ করা হয়
- ক্যাশে হিট৷ :পরবর্তী অভিন্ন প্রশ্নগুলি রিলেশনাল ডাটাবেস থেকে পড়া ছাড়াই রেডিস থেকে অবিলম্বে ফিরে আসে
// This query checks Redis first and only reads from the database if needed
const users = await db.select().from(usersTable)
.where(eq(usersTable.status, 'active'))
.$withCache(); লেখার ক্রিয়াকলাপগুলির জন্য স্মার্ট অবৈধকরণ
লেখার ক্রিয়াকলাপের সময় যাদুটি ঘটে। যখন আপনি আপনার রিলেশনাল ডাটাবেসে ডেটা পরিবর্তন করেন, তখন আমাদের ইন্টিগ্রেশন স্বয়ংক্রিয়ভাবে:
- নির্ভরতা চিহ্নিত করে :কোন ক্যাশে করা প্রশ্নগুলি পরিবর্তিত টেবিলের উপর নির্ভর করে তা নির্ধারণ করে
- ব্যাচ অবৈধকরণ :সমস্ত প্রভাবিত ক্যাশে এন্ট্রি সরিয়ে দেয়
// This insert automatically invalidates all cached queries that depend on usersTable
await db.insert(usersTable).values({
email: 'new@user.com',
status: 'active'
}); একটি সাধারণ ক্যাশে তৈরি করা:"নিষ্পাপ" পদ্ধতি
আমাদের ক্যাশিং ইন্টিগ্রেশন যে সমস্যাগুলি সমাধান করে তা বোঝার জন্য আসুন সহজতম সম্ভাব্য বাস্তবায়ন দিয়ে শুরু করি। একটি প্রশ্নের ফলাফল ক্যাশ করার সময়, আমাদের করতে হবে:
- ক্যাশে করা মান সংরক্ষণ করুন
- এই প্রশ্নটি অবৈধ হওয়ার জন্য কোন টেবিলের উপর নির্ভর করে তা ট্র্যাক করুন
সাধারণ ক্যাশে স্টোরেজ
// When adding an item to the cache
await redis.set(itemHash, cachedValue);
await Promise.all(
dependentTables.map((table) => redis.sadd(table, itemHash))
); এই পদ্ধতিটি ক্যাশ করা ফলাফলকে একটি মূল-মান পেয়ার হিসাবে সঞ্চয় করে এবং প্রতিটি নির্ভরশীল টেবিলের নামকৃত সেটে আইটেম হ্যাশ যোগ করে নির্ভরতা ট্র্যাক করে।
সাধারণ ক্যাশে অবৈধকরণ
// When invalidating based on table changes
const hashesToInvalidate = await redis.sunion(dependentTables);
await redis.del(...hashesToInvalidate); এটি পরিবর্তিত টেবিলের উপর নির্ভর করে এমন সমস্ত ক্যাশ করা আইটেম খুঁজে বের করে, তারপর সেগুলিকে মুছে ফেলার মাধ্যমে কাজ করে৷
এই "সরল" পদ্ধতির সমস্যাগুলি
যদিও এটি প্রযুক্তিগতভাবে কাজ করে, এই নিরীহ বাস্তবায়নের দুটি কার্যকারিতা সমস্যা রয়েছে৷
সমস্যা 1:একাধিক রাউন্ড ট্রিপ
অবৈধকরণ প্রক্রিয়ার জন্য দুটি পৃথক Redis অপারেশন প্রয়োজন৷ :
- প্রথমে, আমরা কল করি
SUNIONমুছে ফেলার জন্য কীগুলির তালিকা পেতে - তারপর, আমরা কল করি
DELধাপ 1
থেকে ফলাফল সহ
এটি একটি রাউন্ড-ট্রিপ নির্ভরতা তৈরি করে যেখানে দ্বিতীয় অপারেশনটি প্রথমটি সম্পূর্ণ হওয়ার জন্য অপেক্ষা করতে হবে৷
সমস্যা 2:ধীরে ধীরে ভর মুছে ফেলা
DEL অনেক কী অকার্যকর করার সময় কমান্ড একটি বাধা হয়ে দাঁড়াতে পারে:
// This could potentially delete thousands of keys
await redis.del(...hashesToInvalidate);
যখন আপনার কাছে একটি জনপ্রিয় টেবিল থাকে যেমন users যেটি শত শত ক্যাশে করা প্রশ্নের দ্বারা উল্লেখ করা হয়েছে, একটি একক আপডেট শত শত পৃথক রেডিস কী মুছে ফেলার কারণ হতে পারে। শত শত বা হাজার হাজার কী সহ, এটি সম্ভবত খুব ধীর হয়ে যেতে পারে৷
সমাধান 1:লুয়া স্ক্রিপ্ট
লুয়া স্ক্রিপ্ট মূল্যায়নের জন্য Upstash Redis-এর সম্পূর্ণ সমর্থন রয়েছে।
লুয়া স্ক্রিপ্ট সার্ভার সাইডে একাধিক Redis কমান্ড কার্যকর করার মাধ্যমে রাউন্ড-ট্রিপ সমস্যার সমাধান করে:
-- Invalidation script that combines SUNION and DEL
local tables = KEYS -- table names passed as keys
local keysToDelete = {}
if #tables > 0 then
-- Get all hashes that depend on these tables
local hashesToInvalidate = redis.call('SUNION', unpack(tables))
-- Prepare for deletion
for _, hash in ipairs(hashesToInvalidate) do
keysToDelete[#keysToDelete + 1] = hash
end
-- Add table sets themselves to deletion list
for _, table in ipairs(tables) do
keysToDelete[#keysToDelete + 1] = table
end
-- Single atomic deletion
if #keysToDelete > 0 then
redis.call('DEL', unpack(keysToDelete))
end
end লুয়া স্ক্রিপ্টের সুবিধা:
- একক রাউন্ড ট্রিপ :সমস্ত অপারেশন সার্ভার-সাইড হয়
- কমিত বিলম্ব৷ :অপারেশনগুলির মধ্যে কোনও নেটওয়ার্ক ওভারহেড নেই
- সঙ্গতি :নেটওয়ার্ক সমস্যার কারণে আংশিক আপডেটের কোনো ঝুঁকি নেই
সমাধান 2:দক্ষ মুছে ফেলার জন্য হ্যাশ-ভিত্তিক স্টোরেজ
এমনকি Lua স্ক্রিপ্টের সাথে, শত শত পৃথক কী মুছে ফেলা আমাদের পছন্দের চেয়ে ধীর হতে পারে। রেডিস হ্যাশ অনেক বেশি কার্যকর সমাধান প্রদান করে:
হ্যাশ-ভিত্তিক পদ্ধতি
প্রতিটি ক্যাশে করা ক্যোয়ারীকে আলাদা রেডিস কী হিসাবে সংরক্ষণ করার পরিবর্তে, আমরা একই টেবিলের উপর নির্ভর করে হ্যাশে গোষ্ঠীভুক্ত প্রশ্নগুলিকে:
// Old approach: Each query gets its own key
await redis.set('query_hash_1', result1);
await redis.set('query_hash_2', result2);
await redis.set('query_hash_3', result3);
// New approach: Group queries by table dependencies
const compositeKey = 'users,posts'; // hash key for users and posts tables
await redis.hset(compositeKey, {
'query_hash_1': result1,
'query_hash_2': result2,
'query_hash_3': result3
}); কেন হ্যাশগুলি অনেক দ্রুত হয়
users-এর উপর নির্ভরশীল প্রশ্নগুলিকে বাতিল করার সময় টেবিল:
// Old way: Delete many individual keys (slow)
await redis.del('query_hash_1', 'query_hash_2', /* ...hundreds more... */);
// New way: Delete entire hash table (fast)
await redis.del('__CT__users,posts'); পারফরম্যান্স সুবিধা:
- একক মোছা অপারেশন :একটি
DELকমান্ড শত শত ক্যাশে করা প্রশ্ন সরিয়ে দেয় - মেমরি দক্ষতা :Redis একটি অপারেশনে সম্পূর্ণ হ্যাশ টেবিল মুক্ত করতে পারে
- পারমাণবিক পরিষ্কার :সমস্ত সম্পর্কিত প্রশ্ন একসাথে বাতিল করা হয়েছে
লুয়া স্ক্রিপ্টগুলি শেষ পর্যন্ত দেখতে কেমন তা দেখতে, আপনি ড্রিজল রিপোজিটরিতে বাস্তবায়ন পরীক্ষা করতে পারেন৷
দানাদার নিয়ন্ত্রণের জন্য ক্যাশে ট্যাগ
টেবিল-ভিত্তিক অবৈধকরণের বাইরে, ড্রিজল সূক্ষ্ম ক্যাশে নিয়ন্ত্রণের জন্য কাস্টম ট্যাগ সমর্থন করে:
// Cache with a custom tag
const premiumUsers = await db.select().from(usersTable)
.where(eq(usersTable.plan, 'premium'))
.$withCache({ tag: 'premium_users' });
// Later, invalidate just this specific query
await db.$cache?.invalidate({ tags: 'premium_users' }); স্বয়ংক্রিয় বনাম ম্যানুয়াল অবৈধকরণ
স্বয়ংক্রিয় অবৈধকরণ (ডিফল্ট):নির্ভরশীল সারণীগুলি পরিবর্তন হলে প্রশ্নগুলি অবৈধ হয়ে যায়, ডেটা সামঞ্জস্য নিশ্চিত করে কিন্তু আরও আক্রমনাত্মক ক্যাশে ক্লিয়ারিং সহ৷
ম্যানুয়াল অবৈধকরণ :এমন পরিস্থিতিতে যেখানে চূড়ান্ত সামঞ্জস্য গ্রহণযোগ্য, আপনি স্বয়ংক্রিয়-অবৈধতা অক্ষম করতে পারেন এবং কখন ক্যাশে সাফ করতে হবে তা ম্যানুয়ালি নিয়ন্ত্রণ করতে পারেন:
// Won't be automatically invalidated - good for analytics data
const monthlyStats = await db.select()
.from(analyticsTable)
.$withCache({ autoInvalidate: false });
// Manually invalidate when needed (e.g., daily batch job)
await db.$cache?.invalidate({ tables: ['analyticsTable'] }); বাস্তব-বিশ্ব ব্যবহারের ক্ষেত্রে
এখন যেহেতু আমরা ইন্টিগ্রেশনের প্রযুক্তিগত দিকটি কভার করেছি, আসুন দেখি কীভাবে এই ধারণাগুলি ব্যবহারিক প্রয়োগে রূপান্তরিত হয়৷
ই-কমার্স পণ্য ক্যাটালগ
// Cache product listings with automatic invalidation
const products = await db.select()
.from(productsTable)
.where(eq(productsTable.active, true))
.$withCache({ tag: 'active_products' });
// When inventory changes, cache is automatically invalidated
await db.update(productsTable)
.set({ stock: newStock })
.where(eq(productsTable.id, productId)); কন্টেন্ট ম্যানেজমেন্ট
// Cache published articles with manual invalidation
const articles = await db.select()
.from(articlesTable)
.where(eq(articlesTable.status, 'published'))
.$withCache({
autoInvalidate: false,
tag: 'published_articles'
});
// Manually invalidate when content is updated
await db.$cache?.invalidate({ tags: 'published_articles' }); উপসংহার
Upstash Redis &Drizzle ক্যাশিং ইন্টিগ্রেশন SQL ক্যোয়ারী কর্মক্ষমতা ব্যাপকভাবে উন্নত করতে পারে এবং (সুন্দর) ন্যূনতম কোড পরিবর্তনের সাথে ডাটাবেস লোড কমাতে পারে।
আপনি যখন ক্যাশে সক্ষম করবেন, তখন আপনি আশা করতে পারেন:
- নাটকীয়ভাবে দ্রুত ক্যাশে করা ডেটার জন্য প্রশ্নের উত্তরের সময়
- কমিত ডাটাবেস লোড এবং উন্নত মাপযোগ্যতা
Upstash Redis এর গ্লোবাল ডিস্ট্রিবিউশন এবং সার্ভারহীন-প্রথম আর্কিটেকচার যার সাথে পে-অ্যাজ-ইউ-গো প্রাইসিং আধুনিক অ্যাপ্লিকেশনের জন্য একটি দুর্দান্ত ভিত্তি৷
ই-কমার্স প্ল্যাটফর্ম, অ্যানালিটিক্স ড্যাশবোর্ড, কন্টেন্ট ম্যানেজমেন্ট সিস্টেম এবং আরও অনেক কিছুর জন্য উপযুক্ত।
আরো পড়া
আরও গভীরে যেতে চান? এখানে কিছু দুর্দান্ত সংস্থান রয়েছে যা আমি আপনাকে চেক আউট করার পরামর্শ দিচ্ছি:
- আপস্ট্যাশ রেডিস এবং ড্রিজল ইন্টিগ্রেশন গাইড
- ড্রিজল ক্যাশিং ডকুমেন্টেশন
- Upstash Redis দিয়ে শুরু করা
- Upstash রেট লিমিট SDK (TypeScript) - আরেকটি শক্তিশালী SDK যা সর্বোত্তম কর্মক্ষমতার জন্য লুয়া স্ক্রিপ্টগুলিকে কাজে লাগায়
- Upstash রেট লিমিট SDK (Python) - রেট লিমিট SDK-এর পাইথন বাস্তবায়ন।