Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Redis

Lua के साथ Redis स्क्रिप्टिंग में मास्टरी: एक व्यावहारिक गाइड

आपने सुना है कि Redis में एक एम्बेडेड स्क्रिप्टिंग भाषा है, लेकिन अभी तक इसे आजमाया नहीं है? यहां आपके Redis सर्वर के साथ Lua की शक्ति का उपयोग करने के लिए आपको जो समझने की आवश्यकता है उसका एक दौरा है।

नमस्ते, Lua!

हमारा पहला Redis Lua स्क्रिप्ट केवल एक वैल्यू लौटाता है बिना वास्तव में किसी भी सार्थक तरीके से Redis के साथ इंटरैक्ट किए:

local msg = "Hello, world!" return msg

यह उतना ही सरल है जितना यह मिलता है। पहली लाइन हमारे मैसेज के साथ एक लोकल वेरिएबल सेट करती है, और दूसरी लाइन उस वैल्यू को Redis सर्वर से क्लाइंट को लौटाती है। इस फ़ाइल को स्थानीय रूप से hello.lua के रूप में सहेजें और इसे ऐसे चलाएं:

redis-cli --eval hello.lua

कनेक्टिविटी समस्याएं?

यह redis-cli उदाहरण मानता है कि आप स्थानीय रूप से एक Redis सर्वर चला रहे हैं। यदि आप RedisGreen जैसे रिमोट सर्वर के साथ काम कर रहे हैं, तो आपको होस्ट और पोर्ट जानकारी निर्दिष्ट करने की आवश्यकता होगी। अपने सर्वर के लिए लॉगिन जानकारी जल्दी से कॉपी करने के लिए अपने RedisGreen डैशबोर्ड पर Connect बटन ढूंढें।

यह भी देखें: Could not connect to Redis at 127.0.0.1:6379: Connection refused.

इसे चलाने से "Hello, world!" प्रिंट होगा। EVAL का पहला आर्ग्यूमेंट पूरा Lua स्क्रिप्ट है — यहां हम फ़ाइल से स्क्रिप्ट पढ़ने के लिए cat कमांड का उपयोग कर रहे हैं। दूसरा आर्ग्यूमेंट उन Redis कीज़ की संख्या है जिन्हें स्क्रिप्ट एक्सेस करेगी। हमारा सरल "Hello World" स्क्रिप्ट किसी भी की को एक्सेस नहीं करता है, इसलिए हम 0 का उपयोग करते हैं।

कीज़ और आर्ग्यूमेंट्स एक्सेस करना

मान लीजिए हम एक URL-शॉर्टनर बना रहे हैं। हर बार एक URL आने पर हम उसे स्टोर करना चाहते हैं और एक यूनिक नंबर लौटाना चाहते हैं जिसका उपयोग बाद में URL को एक्सेस करने के लिए किया जा सके।

हम Redis से INCR का उपयोग करके एक यूनिक ID प्राप्त करने के लिए एक Lua स्क्रिप्ट का उपयोग करेंगे और तुरंत URL को यूनिक ID द्वारा की गई एक हैश में स्टोर करेंगे:

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 को एक्सेस कर रहे हैं। टेबल्स असोसिएटिव ऐरे हैं, और डेटा को स्ट्रक्चर करने के लिए Lua का एकमात्र तंत्र। हमारे उद्देश्यों के लिए आप उन्हें किसी भी भाषा में ऐरे के समकक्ष के रूप में सोच सकते हैं जिसमें आप सबसे अधिक सहज हैं, लेकिन इन दो Lua-वादों पर ध्यान दें जो भाषा में नए लोगों को भ्रमित करते हैं:

  • टेबल्स वन-बेस्ड हैं, अर्थात इंडेक्सिंग 1 से शुरू होती है। तो mytable में पहला एलिमेंट mytable[1] है, दूसरा mytable[2] है, आदि।

  • टेबल्स निल वैल्यूज़ नहीं रख सकते। यदि कोई ऑपरेशन [ 1, nil, 3, 4 ] की एक टेबल देगा, तो परिणाम इसके बजाय [ 1 ] होगा — टेबल पहले निल वैल्यू पर ट्रंकेट हो जाती है।

जब हम इस स्क्रिप्ट को इनवोक करते हैं, तो हमें KEYS और ARGV टेबल्स के लिए वैल्यूज़ भी पास करने की आवश्यकता होती है। रॉ Redis प्रोटोकॉल में, कमांड इस तरह दिखता है:

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

EVAL को कॉल करते समय, स्क्रिप्ट के बाद हम 2 प्रदान करते हैं उन KEYS की संख्या के रूप में जिन्हें एक्सेस किया जाएगा, फिर हम अपने KEYS सूचीबद्ध करते हैं, और अंत में हम ARGV के लिए वैल्यूज़ प्रदान करते हैं।

आम तौर पर जब हम Redis Lua स्क्रिप्ट्स के साथ ऐप्स बनाते हैं, तो Redis क्लाइंट लाइब्रेरी की संख्या निर्दिष्ट करने का ख्याल रखेगी। उपरोक्त कोड ब्लॉक पूर्णता के लिए दिखाया गया है, लेकिन कमांड लाइन पर इसे करने का आसान तरीका यहां है:

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 टेबल पैरामीटर-पासिंग के लिए उपयोग किया जाता है — यहां यह वह URL का वैल्यू है जिसे हम स्टोर करना चाहते हैं।

शर्तीय तर्क: increx और hincrex

हमारा उपरोक्त उदाहरण हमारे URL-शॉर्टनर के लिए लिंक को सेव करता है, लेकिन हमें यह भी ट्रैक करने की आवश्यकता है कि एक URL को कितनी बार एक्सेस किया गया है। ऐसा करने के लिए हम Redis में एक हैश में एक काउंटर रखेंगे। जब कोई उपयोगकर्ता लिंक आइडेंटिफायर के साथ आता है, तो हम जांचेंगे कि क्या यह मौजूद है, और यदि हां तो इसके लिए अपना काउंटर इन्क्रीमेंट करेंगे:

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 पास करते हैं और पिछली स्क्रिप्ट से लौटाए गए लिंक आइडेंटिफायर को सिंगल आर्ग्यूमेंट के रूप में।

स्क्रिप्ट हैश के बिना लगभग समान दिखेगी। यहां एक स्क्रिप्ट है जो एक स्टैंडर्ड Redis की को केवल तभी इन्क्रीमेंट करती है जब वह मौजूद हो:

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

SCRIPT LOAD और EVALSHA

याद रखें कि जब Redis एक Lua स्क्रिप्ट चला रहा होता है, तो यह कुछ और नहीं चलाएगा। सबसे अच्छे स्क्रिप्ट्स केवल मौजूदा Redis वोकैबुलरी को छोटे एटॉमिक डेटा ऑपरेशन्स के साथ आवश्यक न्यूनतम तर्क के साथ बढ़ाते हैं। Lua स्क्रिप्ट्स में बग्स पूरी तरह से Redis सर्वर को लॉक कर सकते हैं — चीजों को छोटा और डीबग करने में आसान रखना सबसे अच्छा है।

भले ही वे आमतौर पर काफी छोटे हों, हमें हर बार जब हम एक चलाना चाहते हैं तो पूरा Lua स्क्रिप्ट निर्दिष्ट करने की आवश्यकता नहीं है। एक वास्तविक एप्लिकेशन में आप अपने प्रत्येक Lua स्क्रिप्ट को Redis के साथ रजिस्टर करेंगे जब आपका एप्लिकेशन बूट होता है (या जब आप डिप्लॉय करते हैं), फिर बाद में उनके यूनिक SHA-1 आइडेंटिफायर द्वारा स्क्रिप्ट्स को कॉल करेंगे।

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

SCRIPT LOAD की एक स्पष्ट कॉल आमतौर पर लाइव एप्लिकेशन में अनावश्यक होती है क्योंकि EVAL पास किए गए स्क्रिप्ट को निहित रूप से लोड करता है। एक एप्लिकेशन आशावादी रूप से EVALSHA का प्रयास कर सकता है और केवल तभी EVAL पर वापस आ सकता है जब स्क्रिप्ट नहीं मिलती।

यदि आप एक Ruby प्रोग्रामर हैं, तो Shopify के Wolverine पर एक नज़र डालें, जो Ruby ऐप्स के लिए Lua स्क्रिप्ट्स के लोडिंग और स्टोरिंग को सरल बनाता है। PHP प्रोग्रामर्स के लिए, Predis Lua स्क्रिप्ट्स को जोड़ने का समर्थन करता है ताकि उन्हें सामान्य Redis कमांड्स की तरह ही बुलाया जा सके। यदि आप Lua के साथ अपनी इंटरैक्शन को मानकीकृत करने के लिए इन या अन्य टूल्स का उपयोग करते हैं, तो मुझे बताएं - मुझे यह पता लगाने में दिलचस्पी होगी कि वहां और क्या है।

Lua कब उपयोग करें?

Lua के लिए Redis सपोर्ट WATCH/MULTI/EXEC ब्लॉक्स के साथ कुछ हद तक ओवरलैप करता है, जो ऑपरेशन्स को ग्रुप करते हैं ताकि वे एक साथ निष्पादित हों। तो आप एक को दूसरे पर कैसे चुनते हैं? MULTI ब्लॉक में प्रत्येक ऑपरेशन को स्वतंत्र होने की आवश्यकता होती है, लेकिन Lua के साथ, बाद के ऑपरेशन्स पहले के ऑपरेशन्स के परिणामों पर निर्भर कर सकते हैं। Lua स्क्रिप्ट्स का उपयोग उन रेस कंडीशन्स से भी बचा सकता है जो धीमे क्लाइंट्स को भूखा कर सकती हैं जब WATCH उपयोग किया जाता है।

हमने RedisGreen पर जो देखा है, उससे अधिकांश ऐप्स जो Lua का उपयोग करते हैं वे MULTI/EXEC का भी उपयोग करेंगे, लेकिन इसके विपरीत नहीं। अधिकांश सफल Lua स्क्रिप्ट्स छोटी होती हैं, और केवल एक सिंगल फीचर को लागू करती हैं जो आपके ऐप को चाहिए लेकिन Redis वोकैबुलरी का हिस्सा नहीं है।

लाइब्रेरी का दौरा

Redis Lua इंटरप्रेटर सात लाइब्रेरीज़ लोड करता है: base, table, string, math, debug, cjson, और cmsgpack। पहले कई स्टैंडर्ड लाइब्रेरीज़ हैं जो आपको किसी भी भाषा से अपेक्षित बेसिक ऑपरेशन्स करने की अनुमति देती हैं। अंतिम दो Redis को JSON और MessagePack समझने देते हैं — यह एक अत्यंत उपयोगी विशेषता है, और मुझे आश्चर्य होता है कि मैं इसे अधिक बार उपयोग होते हुए क्यों नहीं देखता।

पब्लिक APIs वाले वेब ऐप्स में चारों ओर JSON पड़ा होता है। तो शायद आपके पास नॉर्मल Redis कीज़ में स्टोर 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"

इस स्क्रिप्ट को अपने Redis सर्वर में लोड करने से आप Redis में स्टोर JSON वैल्यूज़ को ऐसे ट्रीट कर सकते हैं जैसे वे हैश थे। यदि आपके ऑब्जेक्ट्स उचित रूप से छोटे हैं, तो यह वास्तव में काफी तेज़ है, भले ही हमें प्रत्येक एक्सेस पर वैल्यू को पार्स करना पड़े।

यदि आप एक ऐसे सिस्टम के लिए इंटरनल API पर काम कर रहे हैं जो प्रदर्शन की मांग करता है, तो आप JSON पर MessagePack चुनने की संभावना रखते हैं, क्योंकि यह छोटा और तेज़ है। सौभाग्य से Redis के साथ (अधिकांश स्थानों की तरह), MessagePack 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 के अलग-अलग टाइप सिस्टम हैं, इसलिए यह समझना महत्वपूर्ण है कि Redis-Lua बॉर्डर को पार करते समय वैल्यूज़ कैसे बदल सकती हैं। जब कोई नंबर Lua से वापस Redis क्लाइंट पर आता है, तो यह एक इंटीजर बन जाता है — डेसीमल पॉइंट के बाद के किसी भी अंक को हटा दिया जाता है:

local indiana_pi = 3.2 return indiana_pi

जब आप इस स्क्रिप्ट को चलाते हैं, तो Redis 3 का एक इंटीजर लौटाएगा — आप pi के दिलचस्प टुकड़े खो देते हैं। यह काफी सरल लगता है, लेकिन चीजें थोड़ी अधिक जटिल हो जाती हैं जब आप स्क्रिप्ट के बीच में Redis के साथ इंटरैक्ट करना शुरू करते हैं। एक उदाहरण:

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

यहां परिणामी वैल्यू एक स्ट्रिंग है: "3.2" क्यों? Redis में एक समर्पित न्यूमेरिक टाइप नहीं है। जब हम पहली बार SET करते हैं, तो Redis इसे एक स्ट्रिंग के रूप में सेव करता है, इस तथ्य का सारा रिकॉर्ड खो देता है कि Lua ने शुरुआत में वैल्यू को फ्लोट के रूप में सोचा था। जब हम बाद में वैल्यू को बाहर निकालते हैं, तो यह अभी भी एक स्ट्रिंग है।

GET/SET के साथ एक्सेस की गई Redis में वैल्यूज़ को स्ट्रिंग्स के रूप में सोचा जाना चाहिए सिवाय जब INCR और DECR जैसे न्यूमेरिक ऑपरेशन्स उनके विरुद्ध चलाए जाते हैं। ये विशेष न्यूमेरिक ऑपरेशन्स वास्तव में इंटीजर रिप्लाई लौटाएंगे (और स्टोर की गई वैल्यू को गणितीय नियमों के अनुसार हेरफेर करेंगे), लेकिन Redis में स्टोर की गई वैल्यू का "टाइप" अभी भी एक स्ट्रिंग वैल्यू है।

गॉचाज़: एक सारांश

ये सबसे आम एरर्स हैं जो हम Redis में Lua के साथ काम करते समय देखते हैं:

  • Lua में टेबल्स वन-बेस्ड हैं, अधिकांश लोकप्रिय भाषाओं के विपरीत। KEYS टेबल में पहला एलिमेंट KEYS[1] है, दूसरा KEYS[2] है, आदि।

  • Lua में एक निल वैल्यू एक टेबल को समाप्त करती है। तो [ 1, 2, nil, 3 ] स्वचालित रूप से [1, 2] बन जाएगा। टेबल्स में निल वैल्यूज़ का उपयोग न करें।

  • redis.call Lua एक्सेप्शन-स्टाइल एरर्स उठाएगा, जबकि redis.pcall स्वचालित रूप से किसी भी एरर को ट्रैप करेगा और उन्हें इंस्पेक्टेबल टेबल्स के रूप में लौटाएगा।

  • Lua नंबर्स को Redis को भेजते समय इंटीजर्स में बदल दिया जाता है — डेसीमल पॉइंट के बाद सब कुछ खो जाता है। किसी भी फ्लोटिंग पॉइंट नंबर्स को लौटाने से पहले स्ट्रिंग्स में बदलें।

  • अपने Lua स्क्रिप्ट्स में उपयोग की जाने वाली सभी कीज़ को KEYS टेबल में निर्दिष्ट करना सुनिश्चित करें, अन्यथा आपके स्क्रिप्ट्स शायद Redis के भविष्य के संस्करणों में टूट जाएंगे।

  • Lua स्क्रिप्ट्स Redis में किसी अन्य ऑपरेशन की तरह ही हैं: जब वे निष्पादित हो रहे होते हैं तो कुछ और नहीं चलता। स्क्रिप्ट्स को Redis सर्वर की वोकैबुलरी का विस्तार करने के तरीके के रूप में सोचें — उन्हें छोटा और मुद्दे पर रखें।

आगे पढ़ना

Lua और Redis के लिए ऑनलाइन बहुत सारे बेहतरीन संसाधन हैं — यहां कुछ हैं जिनका मैं उपयोग करता हूं:

  • EVAL डॉक्स
  • RedisGreen की Lua स्क्रिप्ट लाइब्रेरी
  • Lua रेफरेंस मैनुअल
  • Lua ट्यूटोरियल डायरेक्टरी

  1. विंडोज उपयोगकर्ताओं के लिए मैक पर ट्रांजिशन के लिए 7 आवश्यक OS X टिप्स विंडोज उपयोगकर्ताओं के लिए मैक पर ट्रांजिशन के लिए 7 आवश्यक OS X टिप्स

    यदि आपने हाल ही में एक मैक खरीदा है या यदि आपको काम के लिए मैक का उपयोग करना आवश्यक है, तो आप OS X का उपयोग करने की कोशिश करके निराश हो सकते हैं यदि आप लंबे समय से विंडोज उपयोगकर्ता रहे हैं। यह पूरी तरह से समझ में आता है और ऐप्पल वास्तव में अपने OS को विंडोज से मेल खाने के लिए जल्द ही बदलने की परवाह

  1. शानदार शॉट्स कैप्चर करने के लिए टॉप 5 Android फोटोग्राफी ऐप्स शानदार शॉट्स कैप्चर करने के लिए टॉप 5 Android फोटोग्राफी ऐप्स

    आपका Android आपकी रोजमर्रा की गतिविधियों का केंद्र है। आप इसका उपयोग अनगिनत कार्यों के लिए करते हैं; चाहे अपना काम पूरा करना हो या अपने पुराने दोस्तों से जुड़ना हो, यह सिर्फ एक परफेक्ट हैंडी डिवाइस है। आप अपने स्मार्टफोन पर जो कुछ भी करते हैं, उसमें से आप तस्वीरें भी लेते हैं…, और ढेर सारी तस्वीरें।

  1. अल्टीमेट डिस्क क्लीनअप गाइड: Windows और Mac पर स्थान खाली करें अल्टीमेट डिस्क क्लीनअप गाइड: Windows और Mac पर स्थान खाली करें

    आप डिस्क स्थान से बाहर चल रहे हैं, आपका स्टार्टअप डिस्क लगभग भर चुका है - लगभग सभी ने अपने Windows या macOS प्लेटफॉर्म पर इन अपरिहार्य संकेतों का सामना किया है। ठीक वैसे ही जैसे धूल और अव्यवस्था हमारे घरों में छिपे स्थानों में जमा होती है, वही कंप्यूटर मशीनों के लिए कहा जा सकता है। कई अवांछित फ़ाइले