কম্পিউটার

লুয়া:রেডিস ব্যবহারকারীদের জন্য একটি নির্দেশিকা

আপনি শুনেছেন যে রেডিসের একটি এমবেডেড স্ক্রিপ্টিং ভাষা রয়েছে, কিন্তু এখনও এটি চেষ্টা করেননি? আপনার Redis সার্ভারের সাথে Lua-এর ক্ষমতা ব্যবহার করার জন্য আপনাকে যা বুঝতে হবে তার একটি ট্যুর এখানে।

হ্যালো, লুয়া!

আমাদের প্রথম রেডিস লুয়া স্ক্রিপ্ট প্রকৃতপক্ষে কোন অর্থপূর্ণ উপায়ে রেডিসের সাথে ইন্টারঅ্যাক্ট না করেই একটি মান প্রদান করে:

local msg = "Hello, world!"
return msg

এই এটা পায় হিসাবে সহজ. প্রথম লাইনটি আমাদের বার্তার সাথে একটি স্থানীয় পরিবর্তনশীল সেট আপ করে এবং দ্বিতীয় লাইনটি Redis সার্ভার থেকে ক্লায়েন্টে সেই মানটি ফেরত দেয়। এই ফাইলটিকে স্থানীয়ভাবে hello.lua হিসাবে সংরক্ষণ করুন এবং এভাবে চালান:

redis-cli --eval hello.lua

সংযোগ সমস্যা?

এই redis-cli উদাহরণ অনুমান করে যে আপনি স্থানীয়ভাবে একটি রিসার্ভার চালাচ্ছেন। আপনি যদি RedisGreen-এর মতো একটি দূরবর্তী সার্ভারের সাথে কাজ করেন, তাহলে আপনাকে হোস্ট এবং পোর্টের তথ্য নির্দিষ্ট করতে হবে। সংযোগ খুঁজুন আপনার সার্ভারের লগইন তথ্য দ্রুত কপি করতে আপনার RedisGreen ড্যাশবোর্ডে বোতাম।

আরও দেখুন:127.0.0.1:6379 এ Redis এর সাথে সংযোগ করা যায়নি:সংযোগ প্রত্যাখ্যান করা হয়েছে৷

এটি চালানো হলে "হ্যালো, ওয়ার্ল্ড!" প্রিন্ট হবে। EVAL-এর প্রথম আর্গুমেন্ট সম্পূর্ণ লুয়া স্ক্রিপ্ট — এখানে আমরা cat ব্যবহার করছি একটি ফাইল থেকে স্ক্রিপ্ট পড়ার কমান্ড। দ্বিতীয় যুক্তি হল রেডিস্কির সংখ্যা যা স্ক্রিপ্ট অ্যাক্সেস করবে। আমাদের সহজ "হ্যালো ওয়ার্ল্ড" স্ক্রিপ্ট কোনো কী অ্যাক্সেস করে না, তাই আমরা 0 ব্যবহার করি .

কী এবং আর্গুমেন্ট অ্যাক্সেস করা

ধরুন আমরা একটি URL-শর্টনার তৈরি করছি। প্রতিবার যখন একটি URL আসে তখন আমরা সংরক্ষণ করতে চাই এবং একটি অনন্য নম্বর ফেরত দিতে চাই যা পরে URL অ্যাক্সেস করতে ব্যবহার করা যেতে পারে।

আমরা INCR ব্যবহার করে Redis থেকে একটি অনন্য ID পেতে একটি Lua স্ক্রিপ্ট ব্যবহার করব এবং অবিলম্বে ইউআরএলটিকে একটি হ্যাশে সংরক্ষণ করুন যা অনন্য আইডি দ্বারা কী করা হয়:

local link_id = redis.call("INCR", KEYS[1])
redis.call("HSET", KEYS[2], link_id, ARGV[1])
return link_id

call() ব্যবহার করে আমরা এখানে প্রথমবার Redis অ্যাক্সেস করছি ফাংশন।call() এর আর্গুমেন্ট হল Redis-এ পাঠানোর কমান্ড:প্রথমে আমরা INCR <key> ,তারপর আমরা HSET <key> <field> <value> . এই দুটি কমান্ড ক্রমানুসারে চলবে— এই স্ক্রিপ্টটি কার্যকর করার সময় Redis অন্য কিছু করবে না এবং এটি অত্যন্ত দ্রুত চলবে৷

আমরা দুটি Lua টেবিল, KEYS অ্যাক্সেস করছি এবং ARGV . সারণিগুলি হল অ্যাসোসিয়েটিভ অ্যারে, এবং ডেটা গঠনের জন্য লুয়ার একমাত্র প্রক্রিয়া৷ আমাদের উদ্দেশ্যের জন্য আপনি যেকোন ভাষায় যে ভাষাতে আপনি সবচেয়ে স্বাচ্ছন্দ্য বোধ করেন সেগুলিকে একটি অ্যারের সমতুল্য হিসাবে ভাবতে পারেন, তবে এই দুটি লুয়া-ইসম মনে রাখবেন যেগুলি ভাষাতে নতুনদের যাত্রা করে:

  • টেবিলগুলি এক-ভিত্তিক, অর্থাৎ, সূচীকরণ 1 থেকে শুরু হয়। তাই mytable-এ প্রথম উপাদান হল mytable[1] , দ্বিতীয়টি হল mytable[2] , ইত্যাদি।

  • টেবিল শূন্য মান ধরে রাখতে পারে না। যদি একটি অপারেশন [ 1, nil, 3, 4 ] এর একটি সারণী দেয় , ফলাফল পরিবর্তে [ 1 ] হবে — টেবিলটিছেঁটে প্রথম শূন্য মান।

যখন আমরা এই স্ক্রিপ্টটি ব্যবহার করি, তখন আমাদের KEYS-এর মানগুলিও পাস করতে হবে এবং ARGV টেবিল কাঁচা রেডিস প্রোটোকলে, কমান্ডটি এইরকম দেখায়:

EVAL $incrset.lua 2 links:counter links:url https://malcolmgladwellbookgenerator.com/

EVAL কল করার সময় , স্ক্রিপ্টের পরে আমরা 2 প্রদান করি KEYS এর সংখ্যা হিসাবে যেটি অ্যাক্সেস করা হবে, তারপর আমরা আমাদের KEYS তালিকাভুক্ত করি , এবং অবশেষে আমরা ARGV এর জন্য মান প্রদান করি .

সাধারণত আমরা যখন Redis Lua স্ক্রিপ্ট দিয়ে অ্যাপ তৈরি করি, তখন Redisclient লাইব্রেরি কীগুলির সংখ্যা নির্দিষ্ট করার যত্ন নেবে। উপরের কোডব্লকটি সম্পূর্ণতার জন্য দেখানো হয়েছে, কিন্তু কমান্ড লাইনে এটি করার সহজ উপায় এখানে রয়েছে:

redis-cli --eval incrset.lua links:counter links:urls , https://malcolmgladwellbookgenerator.com/

--eval ব্যবহার করার সময় উপরের মত, কমা KEYS[] কে আলাদা করে ARGV[] থেকে আইটেম।

শুধু জিনিসগুলি পরিষ্কার করার জন্য, এখানে আবার আমাদের আসল স্ক্রিপ্ট আছে, এবার KEYS সহ এবং ARGV প্রসারিত:

local link_id = redis.call("INCR", "links:counter")
redis.call("HSET", "links:urls", link_id, "https://malcolmgladwellbookgenerator.com")
return link_id

Redis-এর জন্য Lua স্ক্রিপ্ট লেখার সময়, অ্যাক্সেস করা প্রতিটি কী শুধুমাত্র KEYS দ্বারা অ্যাক্সেস করা উচিত। টেবিল ARGV টেবিলটি প্যারামিটার-পাসিংয়ের জন্য ব্যবহৃত হয় — এখানে আমরা যে ইউআরএল সঞ্চয় করতে চাই তার মান।

শর্তগত যুক্তি:increx এবং hincrex

আমাদের উপরের উদাহরণটি আমাদের URL-সংক্ষিপ্তকারীর জন্য লিঙ্কটি সংরক্ষণ করে, তবে আমাদের একটি URL কতবার অ্যাক্সেস করা হয়েছে তাও ট্র্যাক করতে হবে। এটি করার জন্য আমরা রেডিসে একটি হ্যাশে অ্যাকাউন্ট রাখব। যখন একজন ব্যবহারকারী একটি লিঙ্ক শনাক্তকারীর সাথে আসে, তখন আমরা এটি বিদ্যমান কিনা তা পরীক্ষা করে দেখব, এবং যদি এটি করে তবে এটির জন্য আমাদের কাউন্টার বৃদ্ধি করব:

if redis.call("HEXISTS", KEYS[1], ARGV[1]) == 1 then
  return redis.call("HINCRBY", KEYS[1], ARGV[1], 1)
else
  return nil
end

প্রতিবার যখন কেউ একটি শর্টলিংকে ক্লিক করে, আমরা এই স্ক্রিপ্টটি চালাই যাতে লিঙ্কটি আবার শেয়ার করা হয়েছে। আমরা EVAL ব্যবহার করে স্ক্রিপ্টটি চালু করি এবং links:visits পাস করুন আমাদের একক কী এবং লিঙ্ক শনাক্তকারীর জন্য আমাদের পূর্ববর্তী স্ক্রিপ্ট থেকে একক যুক্তি হিসাবে ফিরে এসেছে৷

হ্যাশ ছাড়া স্ক্রিপ্ট প্রায় একই দেখাবে। এখানে একটি স্ক্রিপ্ট আছে যা একটি স্ট্যান্ডার্ড রেডিস কীকে বৃদ্ধি করে যদি এটি বিদ্যমান থাকে:

if redis.call("EXISTS",KEYS[1]) == 1 then
  return redis.call("INCR",KEYS[1])
else
  return nil
end

স্ক্রিপ্ট লোড এবং ইভালশা

মনে রাখবেন যে রেডিস যখন একটি লুয়া স্ক্রিপ্ট চালাচ্ছে, তখন এটি অন্য কিছু চালাবে না৷ সেরা স্ক্রিপ্টগুলি কেবলমাত্র প্রয়োজনীয় লজিকের ক্ষুদ্রতম বিট সহ ছোট পারমাণবিক ডেটা অপারেশনের বিদ্যমান রেডিস শব্দভাণ্ডারকে প্রসারিত করে৷ লুয়া স্ক্রিপ্টে থাকা বাগগুলি একটি রেডিস সার্ভারকে সম্পূর্ণরূপে লকআপ করতে পারে — জিনিসগুলিকে সংক্ষিপ্ত রাখা এবং ডিবাগ করা সহজ।

যদিও সেগুলি সাধারণত খুব ছোট হয়, প্রতিবার যখন আমরা একটি চালাতে চাই তখন আমাদের সম্পূর্ণ লুয়া স্ক্রিপ্ট নির্দিষ্ট করতে হবে না। একটি বাস্তব অ্যাপ্লিকেশনে আপনি পরিবর্তে আপনার অ্যাপ্লিকেশন বুট করার সময় (বা আপনি যখন স্থাপন করবেন) তখন আপনার প্রতিটি লুয়া স্ক্রিপ্ট রেডিস-এর সাথে নিবন্ধন করবেন, তারপর তাদের অনন্য SHA-1 শনাক্তকারীর মাধ্যমে স্ক্রিপ্টগুলিকে কল করুন।

redis-cli SCRIPT LOAD "return 'hello world'"
# "5332031c6b470dc5a0dd9b4bf2030dea6d65de91"

redis-cli EVALSHA 5332031c6b470dc5a0dd9b4bf2030dea6d65de91 0
# "hello world"

SCRIPT LOAD-এ একটি স্পষ্ট কল EVAL থেকে একটি লাইভ অ্যাপ্লিকেশনে সাধারণত অপ্রয়োজনীয় এটিকে পাস করা স্ক্রিপ্টটি স্পষ্টভাবে লোড করে। একটি অ্যাপ্লিকেশন EVALSHA করার চেষ্টা করতে পারে আশাবাদী এবং EVAL-এ ফিরে যান শুধুমাত্র যদি স্ক্রিপ্ট না পাওয়া যায়।

আপনি যদি একজন রুবি প্রোগ্রামার হন, তাহলে Shopify-এর Wolverine দেখুন, যা রুবি অ্যাপের জন্য লুয়া স্ক্রিপ্ট লোড করা এবং সংরক্ষণ করা সহজ করে। পিএইচপিপ্রোগ্রামারদের জন্য, প্রিডিস লুয়াস্ক্রিপ্ট যোগ করা সমর্থন করে ঠিক যেমন সেগুলি সাধারণ রেডিস কমান্ড ছিল। আপনি যদি লুয়ার সাথে আপনার মিথস্ক্রিয়াকে মানসম্মত করার জন্য এই বা অন্যান্য সরঞ্জামগুলি ব্যবহার করেন, আমাকে জানান- আমি সেখানে আর কী আছে তা খুঁজে পেতে আগ্রহী হব৷

কখন Lua ব্যবহার করবেন?

Lua এর জন্য Redis সমর্থন কিছুটা WATCH এর সাথে ওভারল্যাপ করে /MULTI /EXEC ব্লক, কোন গ্রুপ অপারেশন তাই তারা একসঙ্গে মৃত্যুদন্ড কার্যকর করা হয়. তাহলে আপনি কিভাবে অন্যের উপর একটি ব্যবহার করতে চান? প্রতিটি অপারেশন MULTI-এ ব্লককে স্বাধীন হতে হবে, কিন্তু লুয়ার সাথে, পরবর্তী অপারেশনগুলি আগের অপারেশনগুলির ফলাফলের উপর নির্ভর করে। Lua স্ক্রিপ্ট ব্যবহার করা রেস অবস্থা এড়াতে পারে যা ধীরগতির ক্লায়েন্টদের ক্ষুধার্ত করতে পারে যখন WATCH ব্যবহার করা হয়।

আমরা RedisGreen এ যা দেখেছি তা থেকে, বেশিরভাগ অ্যাপ যেগুলি Lua ব্যবহার করে সেগুলিও MULTI/EXEC ব্যবহার করবে, কিন্তু উল্টো নয়। সর্বাধিক সফল লুয়া স্ক্রিপ্টগুলি ছোট, এবং আপনার অ্যাপের প্রয়োজন এমন একটি বৈশিষ্ট্যকে ন্যায্যভাবে প্রয়োগ করে কিন্তু এটি Redisvocabulary এর অংশ নয়৷

লাইব্রেরি পরিদর্শন

রেডিস লুয়া ইন্টারপ্রেটার সাতটি লাইব্রেরি লোড করে:বেস, টেবিল, স্ট্রিং, ম্যাথ, ডিবাগ, সিজেসন এবং cmsgpack। প্রথম কয়েকটি হল স্ট্যান্ডার্ড লাইব্রেরি যা আপনাকে যে কোনো ভাষা থেকে প্রত্যাশিত মৌলিক ক্রিয়াকলাপগুলি করতে দেয়। শেষ দুটি রেডিসকে JSON এবং MessagePack বুঝতে দেয়— এটি একটি অত্যন্ত দরকারী বৈশিষ্ট্য, এবং আমি ভাবছি কেন আমি এটি আরও বেশিবার ব্যবহার করি না৷

সর্বজনীন API সহ ওয়েব অ্যাপগুলিতে JSON সর্বত্র পড়ে থাকে। তাই হয়ত আপনার কাছে সাধারণ রেডিস কীগুলিতে একগুচ্ছ JSON ব্লব সংরক্ষিত আছে এবং আপনি সেগুলির ভিতরে কিছু নির্দিষ্ট মান অ্যাক্সেস করতে চান, যেন আপনি সেগুলিকে হ্যাশ হিসাবে সংরক্ষণ করেছেন৷ Redis JSON সমর্থন সহ, এটি সহজ:

if redis.call("EXISTS", KEYS[1]) == 1 then
  local payload = redis.call("GET", KEYS[1])
  return cjson.decode(payload)[ARGV[1]]
else
  return nil
end

এখানে আমরা কী বিদ্যমান কিনা তা পরীক্ষা করি এবং না থাকলে দ্রুত শূন্য ফেরত দিই। তারপরে Redis থেকে JSON মানটি বের করুন, এটিকে cjson.decode() দিয়ে পার্স করুন , এবং তার অনুরোধকৃত মান ফেরত দিন।

redis-cli set apple '{ "color": "red", "type": "fruit" }'
# OK

redis-cli --eval json-get.lua apple , type
# "fruit"

আপনার রেডিস সার্ভারে এই স্ক্রিপ্টটি লোড করা হলে আপনি রেডিস-এ সংরক্ষিত JSON মানগুলিকে হ্যাশের মতো আচরণ করতে পারবেন। যদি আপনার বস্তুগুলি যুক্তিসঙ্গতভাবে ছোট হয়, তবে এটি আসলে বেশ দ্রুত, যদিও আমাদের প্রতিটি অ্যাক্সেসের মান বিশ্লেষণ করতে হবে৷

আপনি যদি এমন একটি সিস্টেমের জন্য একটি অভ্যন্তরীণ API-এ কাজ করেন যা কর্মক্ষমতা দাবি করে, তাহলে আপনি JSON-এর উপরে মেসেজপ্যাক বেছে নিতে পারেন, কারণ এটি ছোট এবং দ্রুত৷ সৌভাগ্যবশত রেডিসের সাথে (অধিকাংশ জায়গার মতো), মেসেজপ্যাক একটি ড্রপ-ইনরিপ্লেসমেন্ট৷ JSON এর জন্য:

if redis.call("EXISTS", KEYS[1]) == 1 then
  local payload = redis.call("GET", KEYS[1])
  return cmsgpack.unpack(payload)[ARGV[1]]
else
  return nil
end

ক্রঞ্চিং নম্বর

লুয়া এবং রেডিসের বিভিন্ন ধরণের সিস্টেম রয়েছে, তাই রেডিস-লুয়া সীমান্ত অতিক্রম করার সময় মানগুলি কীভাবে পরিবর্তিত হতে পারে তা বোঝা গুরুত্বপূর্ণ। যখন একটি সংখ্যা Lua থেকে একটি Redis ক্লায়েন্টের কাছে ফিরে আসে, তখন এটি পূর্ণসংখ্যা হয় — দশমিক বিন্দুর পরে যেকোন সংখ্যা বাদ দেওয়া হয়:

local indiana_pi = 3.2
return indiana_pi

আপনি যখন এই স্ক্রিপ্টটি চালাবেন, রেডিস 3 এর একটি পূর্ণসংখ্যা প্রদান করবে — আপনি পাই এর আকর্ষণীয় টুকরোগুলি হারাবেন। যথেষ্ট সহজ বলে মনে হচ্ছে, কিন্তু আপনি যখন স্ক্রিপ্টের মাঝখানে রেডিসের সাথে ইন্টারঅ্যাক্ট শুরু করেন তখন জিনিসগুলি একটু বেশি জটিল হয়ে যায়। একটি উদাহরণ:

local indiana_pi = 3.2
redis.call("SET", "pi", indiana_pi)
return redis.call("GET", "pi")

এখানে ফলস্বরূপ মান হল অ্যাস্ট্রিং:"3.2" কেন? Redis এর একটি ডেডিকেটেড সংখ্যাসূচক প্রকার নেই। যখন আমরা প্রথম SET করি মান, Redis এটি একটি স্ট্রিং হিসাবে সংরক্ষণ করে, লুয়া প্রাথমিকভাবে একটি ফ্লোট হিসাবে মানটি ভেবেছিল তার সমস্ত রেকর্ড হারিয়ে ফেলে। যখন আমরা পরে মানটি বের করি, তখনও এটি একটি স্ট্রিং।

Redis-এ যে মানগুলি GET দিয়ে অ্যাক্সেস করা হয় /SET INCR এর মত সংখ্যাসূচক অপারেশন ছাড়া স্ট্রিং হিসাবে চিন্তা করা উচিত এবং DECR তাদের বিরুদ্ধে চালানো হয়। এই বিশেষ সাংখ্যিক ক্রিয়াকলাপগুলি আসলে পূর্ণসংখ্যার উত্তর দেবে (এবং গাণিতিক নিয়ম অনুসারে সঞ্চিত মানকে ম্যানিপুলেট করবে), তবে রেডিসে সংরক্ষিত মানের "টাইপ" এখনও একটি স্ট্রিং মান৷

গোটচাস:একটি সারাংশ

Redis-এ Lua-এর সাথে কাজ করার সময় এইগুলি সবচেয়ে সাধারণ ত্রুটিগুলি আমরা দেখতে পাই:

  • বেশিরভাগ জনপ্রিয় ভাষার বিপরীতে লুয়াতে টেবিলগুলি এক-ভিত্তিক। KEYS টেবিলের প্রথম উপাদান হল KEYS[1] , দ্বিতীয়টি হল KEYS[2] , ইত্যাদি।

  • একটি শূন্য মান লুয়াতে একটি টেবিলের সমাপ্তি ঘটায়। তাই [ 1, 2, nil, 3 ] স্বয়ংক্রিয়ভাবে [1, 2] হয়ে যাবে . টেবিলে শূন্য মান ব্যবহার করবেন না।

  • redis.call redis.pcall যখন ব্যতিক্রম-শৈলী Lua ত্রুটি উত্থাপন করবে স্বয়ংক্রিয়ভাবে যেকোনো ত্রুটি আটকে দেবে এবং পরিদর্শন করা যেতে পারে এমন অস্থিরতা ফিরিয়ে দেবে।

  • Redis-এ পাঠানোর সময় Lua সংখ্যাগুলিকে পূর্ণসংখ্যায় রূপান্তরিত করা হয় — দশমিক বিন্দুর পরে সবকিছু হারিয়ে যায়। যেকোন ফ্লোটিং পয়েন্ট নম্বরগুলিকে ফেরত দেওয়ার আগে স্ট্রিংয়ে রূপান্তর করুন।

  • KEYS-এ আপনার Lua স্ক্রিপ্টগুলিতে আপনি যে সমস্ত কীগুলি ব্যবহার করেন তা নির্দিষ্ট করতে ভুলবেন না টেবিল, অন্যথায় রেডিসের ভবিষ্যত সংস্করণে আপনার স্ক্রিপ্টগুলি ভেঙে যাবে।

  • লুয়া স্ক্রিপ্টগুলি রেডিসের অন্য যে কোনও অপারেশনের মতোই:সেগুলি চালানোর সময় অন্য কিছুই চলে না। রেডিস সার্ভারের শব্দভাণ্ডার প্রসারিত করার উপায় হিসাবে স্ক্রিপ্টগুলিকে মনে করুন — সেগুলোকে সংক্ষিপ্ত এবং টু-দ্য পয়েন্ট রাখুন।

আরো পড়া

অনলাইনে Lua এবং Redis-এর জন্য প্রচুর দুর্দান্ত সম্পদ রয়েছে — এখানে কয়েকটি Iuse আছে:

  • ইভাল ডক্স
  • রেডিসগ্রিনের লুয়া স্ক্রিপ্ট লাইব্রেরি
  • লুয়া রেফারেন্স ম্যানুয়াল
  • লুয়া টিউটোরিয়াল ডিরেক্টরি

  1. স্ট্রাপির জন্য সার্ভারহীন রেডিস ক্যাশিং

  2. Windows ব্যবহারকারীদের জন্য 7 OS X টিপস

  3. অ্যান্ড্রয়েড ব্যবহারকারীদের জন্য ফটোগ্রাফি গাইড:অ্যান্ড্রয়েডের জন্য 5টি সেরা ফটোগ্রাফি অ্যাপ

  4. ডিস্ক ক্লিনআপ গাইড:উইন্ডোজ এবং ম্যাক ব্যবহারকারীদের জন্য