কম্পিউটার টিউটোরিয়াল

Redis Lua স্ক্রিপ্টিং আয়ত্ত করুন: পারফরম্যান্স বাড়ানোর একটি প্র্যাকটিক্যাল গাইড

লেখক: Andrei Chernikov

Redis একটি জনপ্রিয় ইন-মেমরি গ্রিড যা ইন্টারপ্রসেস কমিউনিকেশন এবং ডেটা স্টোরেজের জন্য ব্যবহৃত হয়। আপনি শুনতে পারেন এটি Lua স্ক্রিপ্ট চালাতে দেয়, কিন্তু আপনি এখনও নিশ্চিত নন কেন। যদি এটা আপনার মতো লাগে, পড়তে থাকুন।

পূর্বশর্ত

এই গাইড ফলো করতে আপনার সিস্টেমে Redis ইনস্টলড থাকা উচিত। পড়ার সময় Redis কমান্ড রেফারেন্স চেক করা হেল্পফুল হতে পারে।

আমাকে Lua স্ক্রিপ্ট কেন দরকার?

সংক্ষেপে: পারফরম্যান্স গেইন। Redis-এ আপনি যা বেশির ভাগ টাস্ক করবেন সেগুলো অনেক ধাপ জড়িত। আপনার অ্যাপ্লিকেশনের ল্যাঙ্গুয়েজে এই ধাপগুলো করার বদলে, আপনি Lua-তে Redis-এর ভিতরে এটি করতে পারেন।

  • এটি ভালো পারফরম্যান্স দিতে পারে।
  • এছাড়া, একটি স্ক্রিপ্টের ভিতরে সব ধাপে এক্সিকিউট হয় একটি অ্যাটমিক ভাবে। স্ক্রিপ্ট এক্সিকিউট হওয়ার সময় অন্য কোনো Redis কমান্ড চলতে পারে না।

উদাহরণস্বরূপ, আমি Lua স্ক্রিপ্ট ব্যবহার করি Redis-এ সংরক্ষিত JSON স্ট্রিংস পরিবর্তন করতে। আমি এটি আর্টিকেলের শেষের দিকে বিস্তারিত বর্ণনা করেছি।

কিন্তু আমি Lua জানি না

Lua না জানা একজন ব্যক্তি

চিন্তা করবেন না, Lua বুঝতে খুব কঠিন নয়। আপনি যদি C ফ্যামিলির যেকোনো ল্যাঙ্গুয়েজ জানেন, আপনি Lua-ও ঠিক থাকবেন। এছাড়া, আমি এই আর্টিকেলে ওয়ার্কিং উদাহরণ দিচ্ছি।

একটি উদাহরণ দেখান

চলুন redis-cli দিয়ে স্ক্রিপ্ট চালানো শুরু করি। এটি চালান:

redis-cli

এখন নিচের কমান্ডটি চালান:

eval "redis.call('set', KEYS[1], ARGV[1])" 1 key:name value

EVAL কমান্ডটিই কী Redis-কে বলে স্ক্রিপ্টটি চালাতে যা এর পরের পার্ট। "redis.call('set', KEYS[1], ARGV[1])" স্ট্রিংটি আমাদের স্ক্রিপ্ট যা ফাংশনালি আইডেন্টিক্যাল Redis-এর set কমান্ডের সাথে। স্ক্রিপ্ট টেক্সটের পর তিনটি প্যারামিটার ফলো করে:

  1. প্রদত্ত কিগুলোর সংখ্যা
  2. কি নাম
  3. প্রথম আর্গুমেন্ট

স্ক্রিপ্ট আর্গুমেন্টগুলো দুটি গ্রুপে পড়ে: KEYS এবং ARGV।

আমরা স্ক্রিপ্টে কতগুলো কি প্রয়োজন সেটি স্ক্রিপ্টের পরের সংখ্যা দিয়ে স্পেসিফাই করি। আমাদের উদাহরণে, এটি ১। এই সংখ্যার ঠিক পরে, আমাদের এই কিগুলো প্রদান করতে হবে, একের পর এক। সেগুলো স্ক্রিপ্টের ভিতরে KEYS টেবিল হিসেবে অ্যাক্সেসযোগ্য। আমাদের কেসে, এটিতে একটি সিঙ্গল ভ্যালু key:name আছে ইনডেক্স ১-এ।

নোট করুন, Lua ইনডেক্সড টেবিল ইনডেক্স ১ দিয়ে শুরু হয়, ০ দিয়ে না।

আমরা কীসের পর যেকোনো সংখ্যক আর্গুমেন্ট প্রদান করতে পারি, যেগুলো Lua-তে ARGV টেবিল হিসেবে উপলব্ধ হবে। এই উদাহরণে, আমরা একটি সিঙ্গল ARGV-আর্গুমেন্ট প্রদান করছি: স্ট্রিং value। আপনি ইতিমধ্যে অনুমান করলেন, উপরের কমান্ডটি কি key:name-কে ভ্যালু value-তে সেট করে।

এটি একটি ভালো প্র্যাকটিস মনে করা হয় স্ক্রিপ্ট যা কিগুলো ব্যবহার করে সেগুলো KEYS-এ প্রদান করা, এবং সব অন্যান্য আর্গুমেন্ট ARGV-এ। তাই আপনাকে KEYS ০ 스페সিফাই করা উচিত নয় এবং তারপর সব কি ARGV টেবিলে প্রদান করা উচিত নয়।

চলুন এখন চেক করি স্ক্রিপ্টটি সফলভাবে সম্পন্ন হয়েছে কিনা। আমরা এটি করব আরেকটি স্ক্রিপ্ট চালিয়ে যেটি Redis-র থেকে কি পাবে:

eval "return redis.call('get', KEYS[1])" 1 key:name

আউটপুট হওয়া উচিত "value", যার মানে পূর্বের স্ক্রিপ্ট সফলভাবে কি "key:name" সেট করেছিল।

স্ক্রিপ্টটি ব্যাখ্যা করতে পারেন?

উপরের স্ক্রিপ্ট দেখে Doge

আমাদের প্রথম স্ক্রিপ্ট একটি সিঙ্গল স্টেটমেন্ট থেকে বানানো: redis.call ফাংশন:

redis.call('set', KEYS[1], ARGV[1])

redis.call দিয়ে আপনি যেকোনো Redis কমান্ড এক্সিকিউট করতে পারেন। প্রথম আর্গুমেন্ট হলো এই কমান্ডের নাম এবং তার প্যারামিটারগুলো। set কমান্ডের কেসে, এই আর্গুমেন্টগুলো হলো key এবং value। সব Redis কমান্ড সাপোর্টেড। ডকুমেন্টেশন অনুযায়ী:

Redis সব কমান্ড চালাতে একই Lua ইন্টারপ্রেটার ব্যবহার করে

আমাদের দ্বিতীয় স্ক্রিপ্ট একটু বেশি করে শুধু একটি কমান্ড চালানোর চেয়ে – এটি একটি ভ্যালুও রিটার্ন করে:

eval "return redis.call('get', KEYS[1])" 1 key:name

স্ক্রিপ্ট দ্বারা রিটার্ন করা সব কিছু কলিং প্রসেসে পাঠানো হয়। আমাদের কেসে, এই প্রসেস হলো redis-cli এবং আপনি আপনার টার্মিনাল উইন্ডোতে রেজাল্ট দেখবেন।

কিছু আরও জটিল?

একজন ব্যক্তি একটি জটিল Redis স্ক্রিপ্ট বানাতে প্ল্যান করছে

আমি একবার Lua স্ক্রিপ্ট ব্যবহার করেছিলাম একটি হ্যাশ ম্যাপ থেকে এলিমেন্ট রিটার্ন করার জন্য একটি নির্দিষ্ট অর্ডারে। অর্ডারটি নিজে হ্যাশ কিগুলো দ্বারা স্পেসিফাই করা হয়েছিল একটি সোর্টেড সেটে স্টোর করা।

চলুন প্রথম আমাদের ডেটা সেট আপ করি এই কমান্ডগুলো redis-cli-এ চালিয়ে:

hmset hkeys key:1 value:1 key:2 value:2 key:3 value:3 key:4 value:4 key:5 value:5 key:6 value:6
zadd order 1 key:3 2 key:1 3 key:2

এই কমান্ডগুলো hkeys কিতে একটি হ্যাশ ম্যাপ তৈরি করে এবং order কিতে একটি সোর্টেড সেট যা hkeys-র সিলেক্টেড কিগুলো একটি নির্দিষ্ট অর্ডারে ধারণ করে।

আপনি চেক করতে চাইতে পারেন hmset এবং zadd কমান্ড রেফারেন্স ডিটেইলসের জন্য।

চলুন নিচের স্ক্রিপ্টটি চালাই:

eval "local order = redis.call('zrange', KEYS[1], 0, -1); return redis.call('hmget',KEYS[2],unpack(order));" 2 order hkeys

আপনাকে নিচের আউটপুট দেখতে মিলবে:

"value:3" "value:1" "value:2"

যার মানে আমরা যে কিগুলো চেয়েছিলাম তাদের ভ্যালু পেয়েছি এবং সঠিক অর্ডারে।

স্ক্রিপ্ট চালাতে কি পূর্ণ স্ক্রিপ্ট টেক্সট স্পেসিফাই করতে হয়?

না! Redis আপনাকে একটি স্ক্রিপ্ট মেমরিতে প্রিলোড করতে দেয় SCRIPT LOAD কমান্ড দিয়ে:

script load "return redis.call('get', KEYS[1])"

আপনাকে এরকম আউটপুট দেখতে মিলবে:

"4e6d8fc8bb01276962cce5371fa795a7763657ae"

এটি স্ক্রিপ্টের ইউনিক হ্যাশ যা আপনাকে EVALSHA কমান্ডে প্রদান করতে হবে স্ক্রিপ্ট চালাতে:

evalsha 4e6d8fc8bb01276962cce5371fa795a7763657ae 1 key:name

নোট: আপনাকে আকচুয়াল SHA1 হ্যাশ ব্যবহার করা উচিত যেটি SCRIPT LOAD কমান্ড দ্বারা রিটার্ন করা হয়েছে, উপরের হ্যাশ শুধু একটি উদাহরণ।

আপনি JSON পরিবর্তন সম্পর্কে কী বললেন?

কখনো কখনো লোকেরা Redis-এ JSON অবজেক্ট সংরক্ষণ করে। এটি ভালো আইডিয়া কিনা সেটি আরেকটি গল্প, কিন্তু প্র্যাকটিসে, এটি অনেক হয়।

যদি আপনাকে এই JSON অবজেক্টে একটি কি পরিবর্তন করতে হয়, আপনাকে Redis-র থেকে এটিকে পেতে হবে, পার্স করতে হবে, কি পরিবর্তন করতে হবে, তারপর সিরিয়ালাইজ করে আবার Redis-এ সেট করতে হবে। এই অ্যাপ্রোচের দুটি সমস্যা রয়েছে:

  1. কনকারেন্সি। অন্য একটি প্রসেস এই JSON কে আমাদের get এবং set অপারেশনের মাঝপথে পরিবর্তন করতে পারে। এই কেসে, পরিবর্তনটি হারিয়ে যাবে।
  2. পারফরম্যান্স। আপনি যদি এই পরিবর্তনগুলো যথেষ্ট često করেন এবং অবজেক্টটি বড় হয়, এটি আপনার অ্যাপের বটলनेक হতে পারে। আপনি Lua-এ এই লজিক ইমপ্লিমেন্ট করে কিছু পারফরম্যান্স জিততে পারেন।

চলুন একটি টেস্ট JSON স্ট্রিং Redis-এ obj কি আন্ডারে যোগ করি:

set obj '{“a”:”foo”,”b”:”bar”}'

এখন আমাদের স্ক্রিপ্টটি চালাই:

EVAL 'local obj = redis.call("get",KEYS[1]); local obj2 = string.gsub(obj,"(" .. ARGV[1] .. "\":)([^,}]+)", "%1" .. ARGV[2]); return redis.call("set",KEYS[1],obj2);' 1 obj b bar2

এখন আমাদের কি obj আন্ডারে নিচের অবজেক্ট থাকবে:

{“a”:”foo”,”b”:”bar2"}

আপনি বদলে এই স্ক্রিপ্টটি লোড করতে পারেন SCRIPT LOAD কমান্ড দিয়ে:

SCRIPT LOAD 'local obj = redis.call("get",KEYS[1]); local obj2 = string.gsub(obj,"(" .. ARGV[1] .. "\":)([^,}]+)", "%1" .. ARGV[2]); return redis.call("set",KEYS[1],obj2);'

এবং তারপর এটি চালান এইভাবে:

EVALSHA <your_script_sha> 1 obj b bar2

কয়েকটি নোট:

  • .. হলো Lua-এ স্ট্রিং কনক্যাটেনেশন অপারেটর।
  • আমরা একটি RegEx প্যাটার্ন ব্যবহার করি কি ম্যাচ করে এর ভ্যালু রিপ্লেস করতে। আপনি যদি এই রেগুলার এক্সপ্রেশন বুঝতে না পারেন, আমার недавি গাইড চেক করতে পারেন।
  • Lua RegEx ফ্লেভারের অন্য ফ্লেভার থেকে একটি পার্থক্য হলো আমরা % ব্যবহার করি যেন ব্যাকরেফারেন্স মার্ক এবং RegEx স্পেশিয়াল সিম্বলস 위한 এস্কেপ ক্যারেক্টার দুইটোই।
  • আমরা এখনো "-কে \ দিয়ে এস্কেপ করি, % দিয়ে না কারণ আমরা Lua স্ট্রিং ডিলিমিটার এস্কেপ করছি, RegEx স্পেশিয়াল সিম্বল নয়।

কি আমি সবসময় Lua স্ক্রিপ্ট ব্যবহার করব?

না। আমি শুধু তখন ব্যবহার করার সুপারিশ করি যখন আপনি প্রুভ করতে পারেন এতে ভালো পারফরম্যান্স আসছে। সবসময় প্রথমে বেঞ্চমার্ক রান করুন।

যদি আপনার চাইশুধু অ্যাটমিকিটি, তবে আপনাকে Redis ট্রানজ্যাকশন চেক করা উচিত।

এছাড়া, আপনার স্ক্রিপ্ট খুব লম্বা হওয়া উচিত নয়। মনে রাখুন যে যতক্ষণ একটি স্ক্রিপ্ট চলছে, সব কিছু অপেক্ষা করছে সেটি ফিনিশ হতে। আপনার স্ক্রিপ্ট যদি কিছুটা টাইম নেয়, এটি বটলनेक তৈরি করতে পারে পারফরম্যান্স উন্নত করার বদলে। স্ক্রিপ্টটি টাইমআউট পৌঁছাতে থামে (ডিফল্ট ৫ সেকেন্ড)।

Redis স্ক্রিপ্টগুলো খুব বেশি টাইম নেওয়া উচিত নয়

শেষ কথা

Lua-র জন্য আরও ইনফরমেশন lua.org-এ পাবেন।

আপনি আমার node.js লাইব্রেরি GitHub-এ চেক করতে পারেন Lua স্ক্রিপ্টের কিছু উদাহরণের জন্য (দेखুন src/lua ফোল্ডার)। আপনি এই লাইব্রেরি node.js-এ ব্যবহার করতে পারেন যেকোনো Lua স্ক্রিপ্ট লিখে JSON অবজেক্ট পরিবর্তন করতে।

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

এই আর্টিকেল পড়ার জন্য ধন্যবাদ। প্রশ্ন এবং মন্তব্য অনেক স্বাগত। আপনি টুইটারে আমাকে ফলো করার জন্যও স্বাগতম।

  1. Oracle Access Manager-এর সাথে Oracle EBS-এর সমন্বিত ইন্টিগ্রেশন シングル সাইন-অনের জন্য

  2. C++-এ Binary Tree Longest Consecutive Sequence: বাইনারি ট্রিতে সর্বোচ্চ সতত ক্রম খুঁজে বের করা

  3. সার্কুলার ট্র্যাকে সবচেয়ে বেশি ভিজিট করা সেক্টর বের করা

  4. HTML DOM Style overflow প্রোপার্টি