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

लुआ:रेडिस उपयोगकर्ताओं के लिए एक गाइड

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

नमस्कार, लुआ!

हमारी पहली रेडिस लुआ स्क्रिप्ट वास्तव में किसी भी सार्थक तरीके से रेडिस के साथ बातचीत किए बिना एक मूल्य लौटाती है:

local msg = "Hello, world!"
return msg

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

redis-cli --eval hello.lua

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

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

यह भी देखें:127.0.0.1:6379 पर Redis से कनेक्ट नहीं हो सका:कनेक्शन अस्वीकृत।

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

कुंजी और तर्कों तक पहुंच बनाना

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

हम INCR . का उपयोग करके Redis से एक अद्वितीय आईडी प्राप्त करने के लिए Lua स्क्रिप्ट का उपयोग करेंगे और यूआरएल को तुरंत एक हैश में स्टोर करें जो कि यूनिक आईडी से कुंजीबद्ध हो:

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

हम पहली बार यहां call() . का उपयोग करके Redis को एक्सेस कर रहे हैं समारोह।call() रेडिस को भेजने के लिए तर्क हैं:पहले हम INCR <key> , तो हम HSET <key> <field> <value> . ये दो आदेश क्रमिक रूप से चलेंगे- इस स्क्रिप्ट के निष्पादित होने के दौरान रेडिस कुछ और नहीं करेगा, और यह बहुत तेज़ी से चलेगा।

हम दो 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-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 हमारी एकल कुंजी के लिए और लिंक पहचानकर्ता हमारी पिछली स्क्रिप्ट से एकल तर्क के रूप में लौटा है।

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

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

SCRIPT LOAD and EVALSHA

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

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

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

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

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

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

लुआ का उपयोग कब करें?

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

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

लाइब्रेरी में जाना

रेडिस लुआ दुभाषिया सात पुस्तकालयों को लोड करता है:आधार, तालिका, स्ट्रिंग, गणित, डिबग, cjson, और cmsgpack। पहले कई मानक पुस्तकालय हैं जो आपको किसी भी भाषा से अपेक्षित बुनियादी संचालन करने की अनुमति देते हैं। अंतिम दो ने रेडिस को JSON और MessagePack को समझने दिया- यह एक अत्यंत उपयोगी विशेषता है, और मैं सोचता रहता हूं कि मैं इसे अधिक बार उपयोग क्यों नहीं करता।

सार्वजनिक एपीआई वाले वेब ऐप्स में 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

यहां हम यह देखने के लिए जांचते हैं कि कुंजी मौजूद है या नहीं और यदि नहीं तो जल्दी से शून्य लौटाएं। फिर रेडिस से JSON मान को वेगेट करें, इसे cjson.decode() with के साथ पार्स करें , और अनुरोधित मान लौटाएं।

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

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

इस स्क्रिप्ट को अपने Redis सर्वर में लोड करने से आप Redis में संग्रहीत 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

क्रंचिंग नंबर

लुआ और रेडिस में अलग-अलग प्रकार की प्रणालियाँ हैं, इसलिए यह समझना महत्वपूर्ण है कि रेडिस-लुआ सीमा पार करते समय मूल्य कैसे बदल सकते हैं। जब कोई संख्या लुआ से रेडिस क्लाइंट के पास वापस आती है, तो यह एक पूर्णांक बन जाती है - दशमलव बिंदु के बाद का कोई भी अंक गिरा दिया जाता है:

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" क्यों? रेडिस के पास एक समर्पित संख्यात्मक प्रकार नहीं है। जब हम पहली बार SET मूल्य, रेडिस इसे एक स्ट्रिंग के रूप में सहेजता है, इस तथ्य के सभी रिकॉर्ड खो देता है कि लुआ ने शुरू में मूल्य को एक फ्लोट के रूप में सोचा था। जब हम बाद में मान निकालते हैं, तब भी यह एक स्ट्रिंग होता है।

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

गोचस:एक सारांश

रेडिस में लुआ के साथ काम करते समय ये सबसे आम त्रुटियां हैं जो हम देखते हैं:

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

  • लुआ में एक शून्य मान एक तालिका को समाप्त करता है। तो [ 1, 2, nil, 3 ] स्वचालित रूप से [1, 2] बन जाएगा . तालिकाओं में शून्य मानों का प्रयोग न करें।

  • redis.call अपवाद-शैली लुआ त्रुटियों को बढ़ाएगा, जबकिredis.pcall स्वचालित रूप से किसी भी त्रुटि को ट्रैप कर देगा और उन्हें उन अस्टेबल्स को वापस कर देगा जिनका निरीक्षण किया जा सकता है।

  • रेडिस को भेजे जाने पर लुआ संख्याओं को पूर्णांक में बदल दिया जाता है - दशमलव बिंदु के बाद का सब कुछ खो जाता है। किसी भी फ़्लोटिंग पॉइंट नंबरों को वापस करने से पहले उन्हें स्ट्रिंग में बदलें।

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

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

आगे पढ़ना

ऑनलाइन लुआ और रेडिस के लिए बहुत सारे महान संसाधन हैं - यहां कुछ Iuse हैं:

  • EVAL डॉक्स
  • रेडिसग्रीन की लुआ स्क्रिप्ट लाइब्रेरी
  • लुआ संदर्भ मैनुअल
  • लुआ ट्यूटोरियल निर्देशिका

  1. विंडोज यूजर्स के लिए 7 OS X टिप्स

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

  1. एंड्रॉइड उपयोगकर्ताओं के लिए फोटोग्राफी गाइड:एंड्रॉइड के लिए 5 सर्वश्रेष्ठ फोटोग्राफी ऐप्स

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

  1. डिस्क क्लीनअप गाइड:Windows और Mac उपयोगकर्ताओं के लिए

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