অনেক মানুষ এবং কোম্পানি যারা Redis ব্যবহার করে সিম্পল ক্যাশিং থেকে মাল্টি-টেরাবাইট সাইজড সেটআপ পর্যন্ত variation-এ, আমার সাথে কথা বলার সুযোগ পাওয়ার কারণে, যে একটি টপিক আমাকে সবচেয়ে বেশি অ্যাড্রেস করতে বলা হয় সেটি হলো পারফরম্যান্স। Redis পারফরম্যান্স অপ্রোচ করার দিক থেকে ভিন্ন। অনেক, যদি অধিকাংশ না হয়, ডেটাবেস সার্ভারে আপনি পারফরম্যান্স উন্নত করার চেষ্টা করেন। Redis-এর সাথে লক্ষ্য হলো এটিকে স্লো না করা। এটি একটি সম্পূর্ণ ভিন্ন অপ্রোচ এবং এটিক সুবিধা নেওয়ার জন্য একটি ভিন্ন মাইন্ডসেট দরকার।
পারফরম্যান্স মেট্রিক্স — ল্যাটেন্সি কি কিং?
Redis ব্যবহার করার সময় মূলত দুটি পারফরম্যান্স মেট্রিক্স থাকে যা আপনি প্রধানত কन्सার্নড থাকবেন: প্রতি সেকেন্ডে কতগুলো কমান্ড (অথবা ট্রানজ্যাকশন) এক্সিকিউট করতে পারি এবং সেগুলো কতক্ষণ লাগে। আপনি যখন ব্রেক ডাউন করেন, আপনি পাবেন पहলেটি দ্বিতীয়টির একটি সেকেন্ডারি ফলাফল। যেহেতু Redis সিংগেল-থ্রেডেড, প্রতি সেকেন্ডে কতগুলো ops পুশ করতে পারবেন সেটি একদম টাইড করে রহে কতক্ষণ লাগে। অতএব, চূড়ান্তে যা মেটার সেটি হলো যা আমি রেফার করি "কমান্ড ল্যাটেন্সি"- হিসেবে।
আমি Redis-এর একটি সুবিধা মনে করি, এর সিম্পলিসিটি। আপনি কমান্ড ইস্যু করেন, কোয়ারী নয়। কমান্ড ডেটা পুল করার একটি অতি সরল পথ, এবং এই কেসে সিম্পলিসিটি কমান্ডের স্পিড-এ রিফ্লেক্ট হয়। এছাড়া এটি ডেভেলপারদের অপ্টিমাইজড কমান্ড প্রদান করার অনুমতি দেয় ভিন্ন ভিন্ন কোয়ারী অপ্টিমাইজ করার চেয়ে। এই ইলিগ্যান্ট সিম্পলিসিটি প্রোগ্রামারদের প্রদান করা হয় যারা Redis কনসুম করে। এটি প্রায়শই মানে "কোয়ারী" টাইপ অপারেশন যেমন একটি সেট ফিল্টার করা, ক্লায়েন্ট সাইডে করা হয় सर्वার সফ্টওয়্যার করবে সেটি না করে।
কিছু লোক মনে করেন এই টাইপের কোয়ারী সার্ভারে একটি কনসিস্টেন্ট উপায়ে করা উচিত, আমি বর্তমানে মতামত এই পথটি আর পছন্দনীয় নয়। কারণ হলো সেই বাগবিয়ার जिसे আমরা "স্কেলেবিলিটি" বলি। আপনি যখন একটি "হরিজন্টালি স্কেলেবল" ওয়েব সার্ভিস বা সাইট চালান শুরু করেন, আপনি প্রায়শই শুরুর দিকে পাবেন এই প্যাটার্ন খুব ভালো কাজ করে। কিন্তু, আপনি যখন "অবিশ্বাস্য" লেভেলের ট্রাফিক হ্যান্ডল करना শুরু করেন, আপনি দ্রুত শিখবেন ডেটাবেস একটি গুরুত্বপূর্ণ বটলনেক। এর পর আপনি শিখবেন এই ডেটাবেস, সাধারণত একটি SQL স্টোর যেমন MySQL, "হরিজন্টালি স্কেলেবল" নয়। আপনি সিম্পলি আরও যোগ করতে পারবেন না।
কমান্ড ল্যাটেন্সি
বিলকুল, Redis-ও নয়। কিন্তু পার্থক্য এখানে যে ফিল্টারিং লজিক, সর্টিং, এবং যেটি আপনি একক Redis কমান্ডে বা সর্বোচ্চ কয়েকটি কমান্ডে এক্সিকিউট করতে পারেন না, সেগুলো রেখে আপনি DB-কে লজিক দিয়ে লোড করছেন না — এবং এভাবে "প্রসেস করার জিনিসগুলো"। Redis কে একটি "ডেটা স্টোর" হিসেবে ব্যবহার করা উচিত, একটি ট্রাডিশনাল "ডেটাবেস সার্ভার" নয়। এটি "Redis স্লো করবেন না" এর প্রথম দিক যা আপনাকে গ্রASP করতে হবে। এর দাবি করা উচিত না যে একবার আপনি Lua স্ক্রিপ্টিং-র পথে যান, আপনি নেট লোয়ার পারফরম্যান্সের রিস্কে পড়েন। আপনি ডেভেলপমেন্টে এটা দেখতে পাবেন না যখন আপনার ট্রাফিক লো থেকে মডারেট। কিন্তু, আপনি বড় স্কেল হিট করলে আপনি এটা দেখবেন। এবং সেটার সময় লজিক অনেক বারের মতোই ইতিমধ্যে বেকড ইন হয়ে যায় এবং অ্যাপ্লিকেশন কোডে মুভ করার জন্য একটি ভারী টেকনিক্যাল ডেট হয়ে যায়। আমরা সবাই জানি টেকনিক্যাল ডেট ক্লিয়ার করার জন্য কত প্রায়োরিটি দেওয়া হয়।
এটার মানে নয় Lua স্ক্রিপ্টিং-র জায়গা নেই। এটার মানে শুধু এটিকে হাইস্ক্রুটিনি করা উচিত। একটি Lua স্ক্রিপ্ট কখন নেট পারফরম্যান্স লস হয় বা নয় সেটার উপর একটি ভাল রুল অফ থাম্ব হলো অ্যাডিশনাল রাউন্ড ট্রিপের খরচ তুলনা করুন যা আপনাকে এক্সিকিউট করতে হতো যদি আপনি সেটি ক্লায়েন্ট-সাইড হ্যান্ডল করতেন। এটি নয়, কিন্তু, আপনার ক্লায়েন্ট কোড কতক্ষণ লাগে সেটি করতে। এটিকে এইভাবে বিবেচনা করুন: আপনি আপনার রাউন্ড ট্রিপ খরচ ২ms কমালে, কিন্তু স্ক্রিপ্ট এক্সিকিউশন টাইমে ৩ms অ্যাড করলে আপনি ভুল ডিরেকশনে গেলে।
এখানে আমাদের কিন রিমেইন সজাগ থাকতে হবে সিংগেল-থ্রেডেড সার্ভারের প্রকৃতি সম্পর্কে। সেটি ৩ms স্ক্রিপ্ট পোটেনশিয়ালি সैंकಡים (হাজার হাজার) কমান্ড ব্লক করছে যতক্ষণ এটি এক্সিকিউট হচ্ছে। আপনি যদি সেগুলো স্প্লিট করেন একটি (পুল) -> (লজিক) -> (পুল) সিকোয়েন্সে, সার্ভার অতিরিক্ত রিকোয়েস্ট প্রসেস করতে পারে "(লজিক)" ফেজগুলোর মধ্যে। লজিক ক্লায়েন্ট কোডে রেখে আপনি মাল্টি-ক্লায়েন্ট বেসড সিস্টেমের ইনহেরেন্ট কনকারেন্সি প্রিজার্ভ করেন। আপনি যদি ট্রানজ্যাকশন বা Lua স্ক্রিপ্টিং প্রয়োজন হয় তাহলে অবশ্যই ব্যবহার করুন। কিন্তু সেগুলো ব্যবহার করবেন না কারণ সেগুলো আপনার কোড "সহজ" করে দিচ্ছে বলে। সবসময় কনকারেন্সি পারফরম্যান্স হিট সম্পর্কে সচেতন থাকুন, এটি মাপুন, এবং সচেতনভাবে চয়ন করুন।
এটি আমাদের "Redis স্লো করবেন না" এর দ্বিতীয় নিয়মে নিয়ে আসে: সার্ভার লজিক ভিয়া স্ক্রিপ্ট এড়িয়ে কনকারেন্সি প্রিজার্ভ করুন। একটি সাইড বেনিফিট হলো Redis ক্লাস্টার সেটআপে মাইগ্রেট করার ক্ষমতা লুয়া স্ক্রিপ্ট রি-রাইট বা ডাম্প কिये বিনা যা মাল্টিপল কী-তে অপারেট করে।
Redis স্লো হতে পারে অন্যান্য উপায়ে
Redis সার্ভার চালানোর কিছু সিস্টেম-লেভেল বা অপারেশনাল দিক রয়েছে যা Redis কে স্লো করতে পারে। যেকোনো সার্ভারের মত I/O রিসোর্স লিমিট Redis কে স্লো করতে পারে। উদাহরণস্বরূপ, আপনার যদি ৮GB নেটওয়ার্ক ব্যান্ডউইডথ প্রয়োজন হয়, কিন্তু ১GB থাকে, এটা আপনার জন্য "স্লো" হবে। আপনার ডেমন প্রসেস যদি কম ওপেন সকেটের লিমিটেড থাকে जितনো কনকারেন্ট কানেকশন আপনার দরকার, টাইম যাবে কানেকশন বন্ধ হওয়ার জন্য অপেক্ষা করতে বাজায় কমান্ড এক্সিকিউট করতে।
সামান্য দুটি অপারেশনাল চয়ন যা Redis কে স্লো করে সেটি হলো ১) একটি ভার্চুয়াল মেশিনে রাখা — বিশেষ করে Xen হাইপারভাইজর ভিত্তিক একটা এবং ২) ভারী ডিস্ক পারসিস্টেন্স।
প্রথমটি স্ট্যান্ডার্ড Redis লিটারেচারে khá ভালোভাবে অ্যাড্রেস করা হয়েছে: Xen হাইপারভাইজর VM-এ রাখবেন না। দ্বিতীয়টি, পারসিস্টেন্স, देखने মনে হয় এটি কিন্তু আমার অনুমানে এটি পর্যাপ্ত দূর যায় নাই।
বেশक, স্ট্যান্ডার্ড রিকমেন্ডেশন রয়েছে: লোকাল ফাস্ট ডিস্ক ব্যবহার করুন, নিশ্চিত করুন আপনার কাছে পর্যাপ্ত মেমরি রয়েছে CoW ড্যান্স হ্যান্ডেল করার জন্য পারসিস্ট করার সময় — এমনকি স্লেভস-ওনলি-এ পারসিস্টেন্স রান করা। এগুলো আপনার কমান্ড ল্যাটেন্সি-তে ইফেক্ট রিপল করতে পারে। যা মিসিং সেটি হলো কীভাবে সঠিকভাবে নির্ধারণ করবেন সেগুলো কি।
এটি টেস্ট করার একটি স্ট্যান্ডার্ড উপায় হলো ইনবিল্ট ল্যাটেন্সি টেস্টিং ব্যবহার করা। টেকনিক্যাল ডিটেইলে যাওয়ার আগে আমি বড় "কীভাবে" প্রশ্নটি অ্যাড্রেস করতে চাই। প্রধান সাবসেট এখানে হলো কখন এই টেস্টগুলো রান করবেন। প্রথমে, এই টেস্ট অর্থহীন হতে পারে যদি আপনার ডেটা সেট ছোট হয়। কত ছোট? নির্ধারণ করুন আপনার ডেটা ডিস্কে ডাম্প করতে কতক্ষণ লাগে। আমরা যদি এক বা দু সেকেন্ড বা দশ সেকেন্ড কথা বলি, আপনি কম চান্স পাবেন অর্থপূর্ণ ডেটা পাওয়ার। অবশ্যই, এটা সবই প্রিডিকেটেড আপনি BGSAVE করছেন SAVE না করে।
পারসিস্টেন্স ল্যাটেন্সি
এটি আমাদের দিকে নিয়ে আসে যা আমি "পারসিস্টেন্স ল্যাটেন্সি" বলে রেফার করি — কমান্ড সার্ভারে হিট করার থেকে রেজাল্ট কোনো ফর্ম অফ পারসিস্টেন্স-এ হিট করার সময়: সেই পারসিস্টেন্স অপশন খুঁজে বের করুন যা সবচেয়ে কম ল্যাটেন্সি ইন্ট্রোডিউস করে। আপনার নেটওয়ার্ক এবং ডিস্কের উপর নির্ভর করে AoF অথবা স্লেভ সার্ভার লোয়েস্ট ল্যাটেন্সি বাম্পিং পারসিস্টেন্স অপশন হবে, RDB লাস্টে আসবে।
RDB লাস্টে আসবে মূলত কারণ এর একটি ইনবিল্ট ডিলে রয়েছে N চেঞ্জেস ওভার T সেকেন্ড। তাই, আপনি যদি সেই মিনিমাল ডুরেশনে পর্যাপ্ত চেঞ্জ পান (স্মলেস্ট ডিফল্ট উইন্ডো ৬০ সেকেন্ড) আপনার পারসিস্টেন্স ডিলে হবে ইন্টারভাল T + RDB ডিস্কে লেখার টাইম। যদি ৩০ সেকেন্ড লাগে সেই মেমরি ডিস্কে ডাম্প করতে ডিফল্ট ৬০ সেকেন্ড ইন্টারভালের সাথে, আপনার "পারসিস্টেন্স ল্যাটেন্সি" হবে (৬০+৩০) ৯০ সেকেন্ড।
এটি যাঁহ, যাঁহ প্রশ্ন উপস্থাপন করে যে এই পারসিস্টেন্স ল্যাটেন্সি কি একটি সমস্যা। এই প্রশ্নের দুটি দিক রয়েছে: ১) আপনার বিজনেস রিকোয়ারমেন্টের জন্য এটি যথেষ্ট কি? এবং ২) এটি আপনার Redis কে স্লো করে কি?
প্রথম প্রশ্নের জন্য আমি একটি জেনেরিক উত্তর দিতে পারি না যা সবার উত্তর দেবে। আমি বলতে পারি, যেন, আপনার পারসিস্টেন্স ল্যাটেন্সি রিকোয়ারমেন্ট টাইট থাকলে উপরের ফর্মুলা যা রিভিল করে তার চেয়ে, আপনার উত্তরগুলো πιθανা ট্রেন্ড করবে "স্লেভ এবং/অথবা AoF ব্যবহার করুন" RDB-এর বদলে। এটি ধরে আপনি আপনার Redis রান করার প্ল্যাটফর্মে স্পষ্ট মিস্টেক করছেন না। যাতে আমরা দ্বিতীয় দিকটিতে আসি: এটি Redis কে স্লো করে কি?
কিছুর জন্য "RDB ফাইল সেভ করতে কতক্ষণ লাগে" সেটি তাদের মাইন্ডে প্যারামাউন্ট হয়ে যায়। আমার দৃষ্টিতে, এটি একটি মিস্টেক। কতক্ষণ লাগে সেটি কি মেটার করে? এই প্রশ্নের উত্তর হলো "কি সেভ Redis কে স্লো করে"। যদি না, তবে আপনাকে কোর নয় যদি এটা ১ সেকেন্ড লাগে বা ১ ঘণ্টা। উদাহরণস্বরূপ, সার্ভার A কনসিডার করুন যা ১০০০ সেকেন্ড নেয় RDB সেভ করতে। সেভ না করার সময় ইনট্রিনসিক কমান্ড ল্যাটেন্সি রেঞ্জ ৩০-১০০ মাইক্রোসেকেন্ড। সেভ করার সময়ও এই ল্যাটেন্সি ৩০-১০০ মাইক্রোসেকেন্ড রেঞ্জে রয়েছে। এই কেসে, এটি প্রিমেচিউর অপ্টিমাইজেশন হবে এই ধারণায় কাজ করা যে আপনার খারাপ Redis পারফরম্যান্স রয়েছে।
তবে সার্ভার B মাত্র ১০ সেকেন্ড নেয়, কিন্তু কমান্ড ল্যাটেন্সি ৩০-১০০us থেকে ১৩০-২৫০us-এ জাম্প করে। এখন আপনার কাছে চিন্তার কারণ রয়েছে কতক্ষণ সেই RDB ফাইল জেনারেট হতে লাগে কারণ সেভ Redis কে স্লো করছে এবং আপনি সেটি মিনিমাইজ করতে চান। যদি সেটি মানে ফাস্টার ডিস্ক, কমপক্ষে এখন আপনার কাছে কারণ রয়েছে সেগুলো জাস্টিফাই করার জন্য — ধরে সেটি ~১০০-১৫০ মাইক্রোসেকেন্ড ইনক্রিজ আপনার অ্যাপ্লিকেশন(গুলো)র জন্য পারফরম্যান্স অ্যানক্সিয়टी সৃষ্টি করে। যদি না করে, তবে আপনি ফিরে যাচ্ছেন প্রিমেচিউর অপ্টিমাইজেশনে।
এখন, কীভাবে সেই ল্যাটেন্সি মাপব সেটি আমি এই পোস্টের পার্ট টু-তে ডিটেইলসে যাব কারণ এটি ইতিমধ্যে খুব লম্বা হয়ে গেছে।