লিখেছেন তারেক এজাজ
আপনি যখন কোনো সফ্টওয়্যার ডিজাইন করছেন তখন পারফরম্যান্স একটি অপরিহার্য প্যারামিটার। এটি বিশেষভাবে গুরুত্বপূর্ণ যখন এটি পর্দার আড়ালে যা ঘটে তা আসে।
আমরা, বিকাশকারী এবং প্রযুক্তিবিদ হিসাবে, কর্মক্ষমতা উন্নত করার জন্য একাধিক পরিবর্তন এবং বাস্তবায়ন গ্রহণ করি। এখানেই ক্যাশিং খেলায় আসে।
ক্যাশিং একটি অস্থায়ী সঞ্চয়স্থানে ডেটা বা ফাইল সংরক্ষণ করার একটি প্রক্রিয়া হিসাবে সংজ্ঞায়িত করা হয় যেখান থেকে যখনই প্রয়োজন তখন তা অবিলম্বে অ্যাক্সেস করা যায়।
আজকাল ওয়েব অ্যাপ্লিকেশনগুলিতে ক্যাশিং একটি আবশ্যক হয়ে উঠেছে। আমরা আমাদের ওয়েব APIগুলিকে সুপারচার্জ করতে Redis ব্যবহার করতে পারি - যেগুলি Node.js এবং MongoDB ব্যবহার করে তৈরি করা হয়েছে৷
"ক্যাশিং দৃশ্যত এখনও 100 থেকে 200 বছর ধরে একটি অত্যন্ত গুরুত্বপূর্ণ ভূমিকা পালন করবে।"
Redis:A Layman's Overview
রেডিস, অফিসিয়াল ডকুমেন্টেশন অনুসারে, একটি ইন-মেমরি ডেটা স্ট্রাকচার স্টোর হিসাবে সংজ্ঞায়িত করা হয় যা একটি ডাটাবেস, বার্তা ব্রোকার বা ক্যাশে স্টোরেজ হিসাবে ব্যবহৃত হয়। এটি স্ট্রিং, হ্যাশ, তালিকা, সেট, রেঞ্জ কোয়েরি সহ সাজানো সেট, বিটম্যাপ, হাইপারলগ, ব্যাসার্ধ প্রশ্ন এবং স্ট্রীম সহ জিওস্পেশিয়াল ইনডেক্সের মতো ডেটা স্ট্রাকচার সমর্থন করে।
ঠিক আছে, যে ডান সেখানে তথ্য কাঠামোর বেশ অনেক. এটিকে সহজ করার জন্য, সমর্থিত প্রায় সমস্ত ডেটা স্ট্রাকচারকে একটি স্ট্রিং বা অন্য ফর্মে ঘনীভূত করা যেতে পারে। আমরা বাস্তবায়নের মধ্য দিয়ে চলার সাথে সাথে আপনি আরও স্পষ্টতা পাবেন।
তবে একটা বিষয় পরিষ্কার। Redis শক্তিশালী, এবং সঠিকভাবে ব্যবহার করা হলে আমাদের অ্যাপ্লিকেশনগুলিকে কেবল দ্রুত নয় কিন্তু আশ্চর্যজনকভাবে দক্ষ করে তুলতে পারে। যথেষ্ট কথা। আসুন আমাদের হাত নোংরা করি।
চলুন কথা বলি কোড
আমরা শুরু করার আগে, আপনাকে আপনার স্থানীয় সিস্টেমে redis সেটআপ পেতে হবে। আপনি এই দ্রুত সেটআপ প্রক্রিয়াটি পুনরায় চালু করতে এবং চালু করতে অনুসরণ করতে পারেন।
হয়েছে? কুল। শুরু করা যাক. আমাদের কাছে এক্সপ্রেসে তৈরি একটি সাধারণ অ্যাপ্লিকেশন রয়েছে যা মঙ্গোডিবি অ্যাটলাসে ডেটা পড়তে এবং লিখতে একটি উদাহরণ ব্যবহার করে।
আমাদের /blogs এ দুটি বড় API তৈরি করা হয়েছে রুট ফাইল।
...
// GET - Fetches all blog posts for required user
blogsRouter.route('/:user')
.get(async (req, res, next) => {
const blogs = await Blog.find({ user: req.params.user });
res.status(200).json({
blogs,
});
});
// POST - Creates a new blog post
blogsRouter.route('/')
.post(async (req, res, next) => {
const existingBlog = await Blog.findOne({ title: req.body.title });
if (!existingBlog) {
let newBlog = new Blog(req.body);
const result = await newBlog.save();
return res.status(200).json({
message: `Blog ${result.id} is successfully created`,
result,
});
}
res.status(200).json({
message: 'Blog with same title exists',
});
});
...
কিছু রেডিস গুডনেস ছিটানো
আমরা npm প্যাকেজ redis ডাউনলোড করে শুরু করি স্থানীয় রেডিস সার্ভারের সাথে সংযোগ করতে।
const mongoose = require('mongoose');
const redis = require('redis');
const util = require('util');
const redisUrl = 'redis://127.0.0.1:6379';
const client = redis.createClient(redisUrl);
client.hget = util.promisify(client.hget);
...
আমরা utils.promisify ব্যবহার করি client.hget রূপান্তর করার ফাংশন একটি কলব্যাক পরিবর্তে একটি প্রতিশ্রুতি ফেরত ফাংশন. আপনি promisification সম্পর্কে আরও পড়তে পারেন এখানে।
Redis সংযোগ জায়গায় আছে. আমরা আরও কোনো ক্যাশিং কোড লেখা শুরু করার আগে, আসুন আমরা একধাপ পিছিয়ে যাই এবং বোঝার চেষ্টা করি যে আমাদের কী কী প্রয়োজনীয়তা পূরণ করতে হবে এবং আমরা যে সম্ভাব্য চ্যালেঞ্জগুলির মুখোমুখি হতে পারি।
আমাদের ক্যাশিং কৌশল নিম্নলিখিত পয়েন্টগুলিকে সম্বোধন করতে সক্ষম হওয়া উচিত৷
- একটি নির্দিষ্ট ব্যবহারকারীর জন্য সমস্ত ব্লগ পোস্টের অনুরোধ ক্যাশে করুন
-
প্রতিবার একটি নতুন ব্লগ পোস্ট তৈরি করার সময় ক্যাশে সাফ করুন
আমাদের কৌশল সম্পর্কে আমাদের সতর্ক থাকা উচিত এমন সম্ভাব্য চ্যালেঞ্জগুলি হল:
-
ক্যাশে ডেটা সংরক্ষণের জন্য কী তৈরি পরিচালনা করার সঠিক উপায়
- ক্যাশের মেয়াদ শেষ হওয়ার যুক্তি এবং ক্যাশে সতেজতা বজায় রাখার জন্য বাধ্যতামূলক মেয়াদ শেষ হওয়া
- ক্যাশিং লজিকের পুনঃব্যবহারযোগ্য বাস্তবায়ন
ঠিক আছে। আমরা আমাদের পয়েন্ট সংক্ষিপ্ত এবং পুনরায় সংযুক্ত আছে. পরবর্তী ধাপে।
ডিফল্ট Mongoose Exec ফাংশন ওভাররাইড করা
আমরা আমাদের ক্যাশিং যুক্তি পুনরায় ব্যবহারযোগ্য হতে চাই. এবং শুধুমাত্র পুনঃব্যবহারযোগ্য নয়, আমরা ডাটাবেসে কোনো প্রশ্ন করার আগে এটিই প্রথম চেকপয়েন্ট হতে চাই। মঙ্গুজ এক্সেক ফাংশনে পিগি-ব্যাকিংয়ের একটি সাধারণ হ্যাক ব্যবহার করে এটি সহজেই করা যেতে পারে।
...
const exec = mongoose.Query.prototype.exec;
...
mongoose.Query.prototype.exec = async function() {
...
const result = await exec.apply(this, arguments);
console.log('Data Source: Database');
return result;
}
...
ক্যোয়ারীতে প্রথম এক্সিকিউশন হিসেবে আমাদের ক্যাশিং লজিক কোড যোগ করতে আমরা মঙ্গুজের প্রোটোটাইপ অবজেক্ট ব্যবহার করি।
কোয়েরি হিসেবে ক্যাশে যোগ করা হচ্ছে
ক্যাশে করার জন্য কোন প্রশ্নগুলি হওয়া উচিত তা বোঝাতে, আমরা একটি মঙ্গুজ কোয়েরি তৈরি করি। আমরা user পাস করার ক্ষমতা প্রদান করি options এর মাধ্যমে একটি হ্যাশ-কি হিসাবে ব্যবহার করতে হবে বস্তু
দ্রষ্টব্য: হ্যাশকি একটি হ্যাশ ডেটা স্ট্রাকচারের জন্য একটি শনাক্তকারী হিসাবে কাজ করে যা, সাধারণ মানুষের ভাষায়, কী-মান জোড়ার সেটের মূল কী হিসাবে বলা যেতে পারে। এইভাবে, ক্যোয়ারী-মান সেটের একটি বৃহত্তর সংখ্যক ক্যাশিং সক্ষম করে৷ আপনি এখানে রেডিসে হ্যাশ সম্পর্কে আরও পড়তে পারেন।
...
mongoose.Query.prototype.cache = function(options = {}) {
this.enableCache = true;
this.hashKey = JSON.stringify(options.key || 'default');
return this;
};
...
এটি করার পরে, আমরা সহজেই cache(<options argument>) ব্যবহার করতে পারি ক্যোয়ারী সহ আমরা নিম্নলিখিত পদ্ধতিতে ক্যাশে করতে চাই।
...
const blogs = await Blog
.find({ user: req.params.user })
.cache({ key: req.params.user });
...
ক্যাশে লজিক তৈরি করা
কোন প্রশ্নগুলি ক্যাশে করা দরকার তা বোঝাতে আমরা একটি সাধারণ পুনঃব্যবহারযোগ্য ক্যোয়ারী সেট আপ করেছি। চলুন এগিয়ে যাই এবং কেন্দ্রীয় ক্যাশিং লজিক লিখি।
...
mongoose.Query.prototype.exec = async function() {
if (!this.enableCache) {
console.log('Data Source: Database');
return exec.apply(this, arguments);
}
const key = JSON.stringify(Object.assign({}, this.getQuery(), {
collection: this.mongooseCollection.name,
}));
const cachedValue = await client.hget(this.hashKey, key);
if (cachedValue) {
const parsedCache = JSON.parse(cachedValue);
console.log('Data Source: Cache');
return Array.isArray(parsedCache)
? parsedCache.map(doc => new this.model(doc))
: new this.model(parsedCache);
}
const result = await exec.apply(this, arguments);
client.hmset(this.hashKey, key, JSON.stringify(result), 'EX', 300);
console.log('Data Source: Database');
return result;
};
...
যখনই আমরা cache() ব্যবহার করি আমাদের প্রধান প্রশ্নের সাথে ক্যোয়ারী, আমরা enableCache সেট করি সত্য হতে চাবিকাঠি.
যদি কী মিথ্যা হয়, আমরা মূল exec ফেরত দিই ডিফল্ট হিসাবে ক্যোয়ারী। যদি না হয়, আমরা প্রথমে ক্যাশে ডেটা আনা এবং সংরক্ষণ/রিফ্রেশ করার জন্য কী তৈরি করি।
আমরা collection ব্যবহার করি স্বতন্ত্রতার জন্য মূল নাম হিসাবে ডিফল্ট প্রশ্নের সাথে নাম। ব্যবহৃত হ্যাশ-কি হল user এর নাম যা আমরা আগেই cache() এ সেট করেছি ফাংশন সংজ্ঞা।
ক্যাশে করা ডেটা client.hget() ব্যবহার করে আনা হয় ফাংশন যার জন্য হ্যাশ-কি এবং পরামিতি হিসাবে ফলস্বরূপ কী প্রয়োজন।
দ্রষ্টব্য: আমরা সবসময় JSON.parse() ব্যবহার করি রেডিস থেকে কোনো ডেটা আনার সময়। এবং একইভাবে, আমরা JSON.stringify() ব্যবহার করি redis-এ কিছু সংরক্ষণ করার আগে কী এবং ডেটাতে। এটি করা হয়েছে যেহেতু redis JSON ডেটা স্ট্রাকচার সমর্থন করে না৷
একবার আমরা ক্যাশে করা ডেটা পেয়ে গেলে, আমাদের প্রতিটি ক্যাশ করা বস্তুকে একটি মঙ্গুজ মডেলে রূপান্তর করতে হবে। এটি কেবল new this.model(<object>) ব্যবহার করে করা যেতে পারে .
যদি ক্যাশে প্রয়োজনীয় ডেটা না থাকে, আমরা ডাটাবেসে একটি ক্যোয়ারী করি। তারপরে, API-এ ডেটা ফেরত দেওয়ার পরে, আমরা client.hmset() ব্যবহার করে ক্যাশে রিফ্রেশ করি . আমরা 300 সেকেন্ডের একটি ডিফল্ট ক্যাশে মেয়াদ শেষ হওয়ার সময়ও সেট করেছি। এটি আপনার ক্যাশিং কৌশলের উপর ভিত্তি করে কাস্টমাইজযোগ্য।
ক্যাশিং যুক্তি জায়গায় আছে. আমরা একটি ডিফল্ট মেয়াদ শেষ হওয়ার সময়ও সেট করেছি। পরবর্তীতে, যখনই একটি নতুন ব্লগ পোস্ট তৈরি করা হয় তখন আমরা জোর করে ক্যাশের মেয়াদ শেষ করার দিকে নজর দিই৷
জোর করে ক্যাশের মেয়াদ শেষ হওয়া
কিছু ক্ষেত্রে, যেমন একজন ব্যবহারকারী যখন একটি নতুন ব্লগ পোস্ট তৈরি করেন, ব্যবহারকারীরা আশা করেন যে নতুন পোস্টটি পাওয়া উচিত যখন তারা সমস্ত পোস্ট আনে।
এটি করার জন্য, আমাদের সেই ব্যবহারকারীর সাথে সম্পর্কিত ক্যাশে সাফ করতে হবে এবং নতুন ডেটা দিয়ে আপডেট করতে হবে। তাই বাধ্য হয়ে মেয়াদ শেষ করতে হবে। আমরা del() ব্যবহার করে তা করতে পারি redis দ্বারা উপলব্ধ ফাংশন.
...
module.exports = {
clearCache(hashKey) {
console.log('Cache cleaned');
client.del(JSON.stringify(hashKey));
}
}
...
আমাদের আরও মনে রাখতে হবে যে আমরা একাধিক রুটে মেয়াদ শেষ করতে বাধ্য করব। একটি এক্সটেনসিবল উপায় হল এই clearCache() ব্যবহার করা একটি মিডলওয়্যার হিসাবে এবং একটি রুট সম্পর্কিত যেকোন কোয়েরি সম্পাদন শেষ হলে এটিকে কল করুন।
const { clearCache } = require('../services/cache');
module.exports = async (req, res, next) => {
// wait for route handler to finish running
await next();
clearCache(req.body.user);
}
এই মিডলওয়্যারটিকে নিম্নলিখিত উপায়ে একটি নির্দিষ্ট রুটে সহজেই কল করা যেতে পারে।
...
blogsRouter.route('/')
.post(cleanCache, async (req, res, next) => {
...
}
...
এবং আমরা সম্পন্ন. আমি সম্মত যে একটি বেশ অনেক কোড ছিল. কিন্তু সেই শেষ অংশের সাথে, আমরা আমাদের অ্যাপ্লিকেশনের সাথে রেডিস সেট আপ করেছি এবং প্রায় সমস্ত সম্ভাব্য চ্যালেঞ্জের যত্ন নিয়েছি। আমাদের ক্যাশিং কৌশলটি কার্যকরভাবে দেখার সময় এসেছে৷
অ্যাকশনে রেডিস
আমাদের ক্যাশিং কৌশলটি কার্যকরভাবে দেখতে আমরা API ক্লায়েন্ট হিসাবে পোস্টম্যান ব্যবহার করি। এই আমরা যাই. চলুন একের পর এক API ক্রিয়াকলাপ চালাই।
- আমরা
/blogsব্যবহার করে একটি নতুন ব্লগ পোস্ট তৈরি করি রুট
নতুন ব্লগ পোস্ট তৈরি৷
- তারপর আমরা ব্যবহারকারী
tejazসম্পর্কিত সমস্ত ব্লগ পোস্ট আনব
ব্যবহারকারী তেজাজের জন্য সমস্ত ব্লগ পোস্ট আনা হচ্ছে
- আমরা
tejazব্যবহারকারীর জন্য সমস্ত ব্লগ পোস্ট নিয়ে আসি আরও একবার।
ইউজার তেজাজের জন্য সব ব্লগ পোস্ট আনুন আরও একবার
আপনি স্পষ্ট দেখতে পাচ্ছেন যে যখন আমরা ক্যাশে থেকে আনব, নেওয়া সময় 409ms থেকে কমে গেছে 24ms পর্যন্ত . এটি প্রায় 95% সময় কমিয়ে আপনার APIকে সুপারচার্জ করে
এছাড়াও, আমরা স্পষ্টভাবে দেখতে পাচ্ছি যে ক্যাশের মেয়াদ শেষ হওয়া এবং আপডেট অপারেশনগুলি প্রত্যাশা অনুযায়ী কাজ করে৷
আপনি সম্পূর্ণ সোর্স কোডটি redis-express-এ খুঁজে পেতে পারেন এখানে ফোল্ডার।
উপসংহার
যেকোন কর্মক্ষমতা-দক্ষ এবং ডেটা-নিবিড় অ্যাপ্লিকেশনের জন্য ক্যাশিং একটি বাধ্যতামূলক পদক্ষেপ। রেডিস আপনাকে আপনার ওয়েব অ্যাপ্লিকেশনে সহজেই এটি অর্জন করতে সহায়তা করে। এটি একটি অতি শক্তিশালী টুল, এবং সঠিকভাবে ব্যবহার করা হলে এটি অবশ্যই ডেভেলপারদের পাশাপাশি চারপাশের ব্যবহারকারীদের একটি চমৎকার অভিজ্ঞতা প্রদান করতে পারে।
আপনি এখানে redis কমান্ডের সম্পূর্ণ সেট খুঁজে পেতে পারেন। আপনি এটি redis-cli দিয়ে ব্যবহার করতে পারেন আপনার ক্যাশে ডেটা এবং অ্যাপ্লিকেশন প্রক্রিয়াগুলি নিরীক্ষণ করতে।
কোনো বিশেষ প্রযুক্তি দ্বারা প্রস্তাবিত সম্ভাবনা সত্যিই অন্তহীন. আপনার যদি কোন প্রশ্ন থাকে, আপনি [LinkedIn](https://www.linkedin.com/in/tarique-ejaz/) এ আমার সাথে যোগাযোগ করতে পারেন .
এই সময়ের মধ্যে, কোডিং করতে থাকুন।
বিনামূল্যে কোড শিখুন. freeCodeCamp-এর ওপেন সোর্স পাঠ্যক্রম 40,000-এরও বেশি লোককে ডেভেলপার হিসেবে চাকরি পেতে সাহায্য করেছে। শুরু করুন