Vercel KV ওয়েব প্রজেক্টের জন্য একটি অমূল্য টুল, তবুও এর ব্যাপক ব্যবহার HTTP অনুরোধের সংখ্যা দ্রুত বৃদ্ধির দিকে নিয়ে যেতে পারে, যা কার্যকারিতাকে প্রভাবিত করতে পারে। রেডিস পাইপলাইনগুলি ব্যাচ কমান্ড এবং অনুরোধগুলি হ্রাস করার একটি উপায় অফার করে, সেগুলি বাস্তবায়ন করা কঠিন হতে পারে। মৌলিক রেডিস কমান্ডের সরলতার সাথে পাইপলাইনের দক্ষতাকে একত্রিত করে এমন একটি সমাধান আছে কি? আসে অটো-পাইপলাইনিং – কোডিং জটিলতা ছাড়াই কর্মক্ষমতা বাড়ানোর জন্য একটি নিরবচ্ছিন্ন উপায় অফার করে৷
সমস্যা
কল্পনা করুন যে আপনি একটি ওয়েবপৃষ্ঠা তৈরি করেছেন যেখানে রেডিস ব্যাপকভাবে ডেটা উত্স হিসাবে ব্যবহৃত হয়। একাধিক কম্পোনেন্ট তাদের নিজস্ব Redis কল করে, কিছু উপাদান বিভিন্ন কন্টেন্টের সাথে একাধিকবার রেন্ডার করা হয়।
এই সেটআপটি প্রতিবার ওয়েবপেজ খোলার সময় Redis-এর কাছে উল্লেখযোগ্য সংখ্যক অনুরোধ তৈরি করতে পারে। অনুরোধের নিছক ভলিউম যথেষ্ট ওভারহেড প্রবর্তন করে, কর্মক্ষমতা প্রভাবিত করে। উপরন্তু, ক্লাউডফ্লেয়ার ওয়ার্কারদের মতো পরিবেশে, যেখানে সমসাময়িক HTTP অনুরোধের সংখ্যা গুরুতরভাবে সীমিত, এটি একটি জটিল সমস্যা হয়ে দাঁড়ায়৷
নিয়মিত পাইপলাইন
এই ধরনের পরিস্থিতিতে একটি প্রচলিত সমাধান হল Redis পাইপলাইন ব্যবহার করা। একের পর এক অনুরোধ পাঠানোর পরিবর্তে, পাইপলাইনগুলি আপনাকে একাধিক কমান্ড সংগ্রহ করতে এবং সেগুলি একসাথে সম্পাদন করতে দেয়। এইভাবে, একটি একক HTTP অনুরোধ একাধিক Redis কমান্ড বহন করে, উল্লেখযোগ্যভাবে HTTP অনুরোধের সংখ্যা হ্রাস করে এবং কর্মক্ষমতা উন্নত করে।
import { kv } from '@vercel/kv';
const pipeline = kv.pipeline();
pipeline.set("foo", "bar");
pipeline.get("foo");
const res = await pipeline.exec();
console.log(res); // ["OK", "bar"] পাইপলাইনের অসুবিধা
যাইহোক, পাইপলাইন ব্যবহার করা একটি প্রোগ্রামারের দৃষ্টিকোণ থেকে উল্লেখযোগ্য ওভারহেডের পরিচয় দেয়। পাইপলাইন এপিআই স্ট্যান্ডার্ড রেডিস এপিআই থেকে আলাদা, এটিকে সক্রিয় বা নিষ্ক্রিয় করা একটি অ-তুচ্ছ কাজ করে তোলে।
অধিকন্তু, যদি আপনাকে একটি একক পাইপলাইনের মধ্যে বিভিন্ন উপাদানের জন্য ডেটা অনুরোধ করতে হয়, তাহলে আপনাকে অবশ্যই ডেটা ব্যবহার করা হবে সেখান থেকে আলাদা করে আনার যুক্তি লিখতে হবে। এই বিচ্ছেদ একটি খণ্ডিত এবং কম রক্ষণাবেক্ষণযোগ্য কোডবেসের দিকে নিয়ে যেতে পারে৷
অটো-পাইপলাইনিং
অটো-পাইপলাইনিং এই সমস্যাগুলিকে নির্বিঘ্নে সমাধান করে। স্বয়ংক্রিয় পাইপলাইনিংয়ের মাধ্যমে, আপনি আপনার বিদ্যমান কোড পরিবর্তন না করেই আপনার প্রকল্পে পাইপলাইন কার্যকারিতা সক্ষম করতে পারেন। আপনি যথারীতি Redis ব্যবহার চালিয়ে যেতে পারেন, যখন Redis ক্লায়েন্ট স্বয়ংক্রিয়ভাবে কমান্ড ব্যাচ করে যখনই সম্ভব, কর্মক্ষমতা বাড়ায় অনায়াসে।
আসুন অন্বেষণ করি কিভাবে স্বয়ংক্রিয়-পাইপলাইনিং একটি সাধারণ দৃশ্যকল্পকে অপ্টিমাইজ করে:একাধিক কীগুলির জন্য মান আনা:
const keys = ["key1", "key2", "key3"];
const values = await Promise.all(keys.map(key => kv.get(key))); পাইপলাইন ছাড়া, এই কোডটি Redis-এ তিনটি HTTP অনুরোধ পাঠাবে। যাইহোক, স্বয়ংক্রিয় পাইপলাইনিং সক্ষম হলে, এই অনুরোধগুলি একটি একক HTTP অনুরোধে ব্যাচ করা হবে৷
ইডিওম্যাটিক রিঅ্যাক্ট সার্ভার উপাদানের জন্য অটো-পাইপলাইন
রিঅ্যাক্ট সার্ভার কম্পোনেন্টস (আরএসসি) তাদের নিজস্ব ডেটা আনতে পারে। একটি সাধারণ উদাহরণ হল একটি টুইট উপাদান যা এভাবে বাস্তবায়িত হতে পারে
async function Tweet({id}) {
const tweet = kv.get(`tweets:${id}`)
return <div>{tweet.text}</div>
} যদি আপনি এই উপাদানটিকে একটি লুপে কল করেন যেমন
{tweetIds.map(id => <Tweet id={id} />)} আপনি উপরের উদাহরণের মতো একই N ব্যাকএন্ড অনুরোধগুলি ট্রিগার করেন। আবারও, স্বয়ংক্রিয়-পাইপলাইনিং ব্যাচ সক্রিয় করা এন কমান্ডগুলিকে একটি একক পাইপলাইনে পরিণত করে যখন ইডিওম্যাটিক রিঅ্যাক্ট কোড বজায় রাখে।
এটি কিভাবে কাজ করে
স্বয়ংক্রিয় পাইপলাইন পটভূমিতে একটি 'সক্রিয় পাইপলাইন' বজায় রেখে কাজ করে। কমান্ডগুলি পাইপলাইনে নিজেদের যুক্ত করে এবং deferExecution আহ্বান করে :
private async deferExecution() {
await Promise.resolve()
return await Promise.resolve()
}
deferExecution কল করলে , কমান্ড Node.js প্রধান থ্রেডের নিয়ন্ত্রণ প্রদান করে। পরবর্তী GET ক্রমানুসারে কমান্ড তারপর থ্রেডের নিয়ন্ত্রণ লাভ করে এবং এটি কার্যকর করার সাথে এগিয়ে যায়, প্রথম GET এর মতো ঠিক একই কাজ করে :সক্রিয় পাইপলাইনে নিজেকে যুক্ত করা এবং থ্রেডের নিয়ন্ত্রণ পাওয়া।
এখানে ছদ্ম-কোড হিসাবে অটো পাইপলাইন যুক্তি আছে:
let activePipeline: Pipeline;
let pipelinePromises: new WeakMap<Pipeline, Promise<Array<unknown>>>();
let commandIndex: number;
const executeCommand = (command) => {
activePipeline = activePipeline || createNewPipeline();
activePipeline.addCommand(command);
commandIndex++;
const pipelinePromise = deferExecution().then(() => {
if (!pipelinePromises.has(activePipeline) {
const pipelinePromise = pipeline.exec();
pipelinePromises.set(pipeline, pipelinePromise);
activePipeline = null;
commandIndex = 0
};
return pipelinePromises.get(activePipeline)!;
});
const result = await pipelinePromise;
return result[commandIndex];
};
সক্রিয় পাইপলাইনে নিজেকে যুক্ত করার পরে, তৃতীয় GET এছাড়াও deferExecution কল করে . এই মুহুর্তে, যেহেতু স্থগিত করা GET এর মধ্যে অন্য কোন কমান্ড নেই কমান্ডগুলি নিয়ন্ত্রণ পুনরুদ্ধার করবে এবং পাইপলাইন কার্যকর করবে৷
এই পাইপলাইনটি আমাদের উদাহরণে তিনটি ফলাফল প্রদান করে, প্রতিটি প্রাথমিক কমান্ডের সাথে সম্পর্কিত। প্রতিটি কমান্ড তার যুক্তির সূচী ট্র্যাক করে, নিশ্চিত করে যে এটি ব্যাচ প্রতিক্রিয়া থেকে সঠিক ফলাফল পেয়েছে।
অটো-পাইপলাইনিং লজিকের পিছনের কোড এখানে পাওয়া যায়।
v0.dev-এ অটো-পাইপলাইনিং
v0.dev-এর কর্মক্ষমতায় অটো-পাইপলাইনিংয়ের প্রভাব ল্যান্ডিং পৃষ্ঠার উন্নতি থেকে স্পষ্ট। ল্যান্ডিং পৃষ্ঠাটি অতীতের প্রশ্ন এবং প্রজন্মের উদাহরণ দেখায়। প্রথমত, এটি প্রদর্শনের জন্য আইটেমগুলির তালিকা নিয়ে আসে এবং তারপরে প্রতিটি আইটেমের জন্য পৃথক আনয়ন করে, যার ফলে অনেকগুলি Redis অনুরোধ আসে৷

স্বয়ংক্রিয় পাইপলাইনিং সক্ষম করার পরে, এই প্রক্রিয়াটি একটি সুইচের ফ্লিপ দিয়ে অপ্টিমাইজ করা হয়। এখন, দ্বিতীয় অংশ, যা একাধিক স্বতন্ত্র আনার সাথে জড়িত ছিল, একটি একক পাইপলাইন অপারেশনে একত্রিত হয়েছে৷
স্বয়ংক্রিয়-পাইপলাইনিং বাস্তবায়নের আগে, এই রেডিস অনুরোধগুলি উল্লেখযোগ্য সংখ্যক পৃথক HTTP অনুরোধের দিকে পরিচালিত করে, পৃষ্ঠা লোডের সময় কমিয়ে দেয়। যাইহোক, স্বয়ংক্রিয়-পাইপলাইনিং সক্ষম করে, এই অনুরোধগুলি দক্ষতার সাথে পাইপলাইনে ব্যাচ করা হয়, প্রয়োজনীয় HTTP অনুরোধের সংখ্যা হ্রাস করে। ফলস্বরূপ, পৃষ্ঠা লোডের সময় উন্নত হয়, প্রায় 450ms থেকে প্রায় 200ms পর্যন্ত হ্রাস পায়৷
v0 টিম প্রাথমিকভাবে নিজেদের জন্য একটি হ্যাক হিসাবে স্বয়ংক্রিয় পাইপলাইনিং পাঠিয়েছে। অটো-পাইপলাইনিং এখন Upstash-এর Redis ক্লায়েন্টের v1.31.3, সেইসাথে Vercel KV-এর v2.0-এ উপলব্ধ৷