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

आप शायद रेडिस स्ट्रीम के बारे में गलत सोच रहे हैं

मैं व्यक्तिगत रूप से गलत तरीके से धाराओं का वर्णन करने के लिए दोषी हूं- मैंने इसे "एक ही कुंजी के तहत, समय के अनुसार क्रमबद्ध हैशपैप-जैसे तत्वों की श्रृंखला" के रूप में परिभाषित किया है। यह गलत है . समय और कुंजी के संबंध में अंतिम बिट ठीक है, लेकिन पहला बिट गलत है।

आइए देखें कि धाराओं को गलत क्यों समझा जाता है और वे वास्तव में कैसे व्यवहार करते हैं। हम इस गलतफहमी के अच्छे और बुरे का मूल्यांकन करेंगे और यह आपके सॉफ़्टवेयर को कैसे प्रभावित कर सकता है। अंत में, हम कुछ गैर-स्पष्ट पैटर्न की जांच करेंगे जो रेडिस स्ट्रीम के अल्पज्ञात गुणों का लाभ उठाते हैं।

पृष्ठभूमि

सबसे पहले, आइए XADD कमांड को देखें, क्योंकि यहीं से गलतफहमी शुरू होती है। कमांड सिग्नेचर जैसा कि यह आधिकारिक redis.io प्रलेखन में है, इस तरह दिखता है:

XADD key ID field value [field value ...]

<चिह्न>कुंजी आत्म-व्याख्यात्मक है। <चिह्न>आईडी नई प्रविष्टि के लिए टाइमस्टैम्प/अनुक्रम कॉम्बो है, लेकिन वास्तव में, ऑटो पीढ़ी को इंगित करने के लिए यह लगभग हमेशा * होता है। इस भ्रम की जड़ क्षेत्र और मूल्य से शुरू होती है। यदि आप HSET के लिए कमांड सिग्नेचर को देखते हैं, तो आपको एक समान पैटर्न दिखाई देगा:

HSET key field value [field value ...]

दो आदेशों के लिए हस्ताक्षर केवल एक ही तर्क बंद है और XADD में वह तर्क लगभग हमेशा एक * है। बहुत समान दिखता है, समान शब्दों का उपयोग करता है, वही होना चाहिए, है ना?

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

यह रेडिस हैश के लिए अच्छी तरह से मैप करता है-ये सभी एक हैश के गुणों को स्पष्ट कर सकते हैं, जो अनियंत्रित है और इसमें कोई दोहराव नहीं है। PHP एरेज़, पायथन डिक्ट्स और जावास्क्रिप्ट मैप्स फील्ड ऑर्डर को परिभाषित कर सकते हैं, लेकिन अगर आप रेडिस में हैश के साथ काम कर रहे हैं, तो इससे कोई फर्क नहीं पड़ता, आपको बस यह जानना होगा कि आप एप्लिकेशन स्तर पर इस ऑर्डर पर निर्भर नहीं रह सकते हैं। ।

ज्यादातर लोगों के लिए, स्वाभाविक निष्कर्ष यह रहा है कि चूंकि एचएसईटी और एक्सएडीडी के कमांड सिग्नेचर में सहसंबंध होता है, तो उनके बदले में शायद एक समान सहसंबंध होता है। दरअसल, आरईएसपी 2 में प्रोटोकॉल स्तर पर, इन दोनों को इंटरलीव्ड आरईएसपी एरेज़ के रूप में वापस कर दिया जाता है। इसे RESP3 के शुरुआती संस्करणों में जारी रखा गया है, जहां HGETALL और XREAD के लिए प्रतिक्रिया दोनों मानचित्र थे (उस पर बाद में अधिक)।

एक बग ने मेरा विचार बदल दिया

आम तौर पर, मैं जावास्क्रिप्ट और कभी-कभी पायथन में कोड करता हूं। जैसा कि कोई है जो रेडिस के बारे में संचार करता है, मुझे अधिक से अधिक लोगों तक पहुंचने की आवश्यकता है और इन दो भाषाओं को बहुत अच्छी तरह से समझा जाता है, इसलिए किसी भी डेमो या नमूना कोड को डेवलपर दुनिया के उच्च प्रतिशत द्वारा समझा जाएगा। हाल ही में, मुझे एक PHP सम्मेलन में बात करने का अवसर मिला और कुछ मौजूदा पायथन कोड को PHP में बदलने की आवश्यकता थी। मैंने लगभग 20 वर्षों से PHP को चालू और बंद किया है, लेकिन यह मेरा जुनून कभी नहीं रहा। विशेष डेमो एक mod_php शैली निष्पादन में अच्छी तरह से फिट नहीं था, इसलिए मैंने swoole और इसके सह-नियमित निष्पादन का उपयोग किया (एक तरफ ध्यान दें, जावास्क्रिप्ट दुनिया में सहज होने के कारण, swoole PHP को बहुत, मेरे लिए बहुत परिचित बनाता है)। पुस्तकालय थोड़ा पुराना था और उच्च स्तर के तरीके से रिटर्न को डीकोड करने में किसी भी वास्तविक क्लाइंट लाइब्रेरी सहायता के बिना कच्चे रेडिस कमांड भेजने की आवश्यकता थी। आम तौर पर, कच्चे रेडिस कमांड भेजना और परिणामों को डिकोड करना थोड़ा अधिक नियंत्रण प्रदान करता है और यह कठिन नहीं है।

इसलिए, XADD को कमांड भेजते समय, मैं फील्ड-वैल्यू वाले हिस्से का निर्माण कर रहा था और इसमें एक-एक-एक त्रुटि थी (इसे कई वर्षों की अनुपस्थिति के बाद PHP में वापस गोता लगाने के लिए चाक करें)। इसका परिणाम यह हुआ कि मुझे अनजाने में निम्न की तर्ज पर कुछ भेजना पड़ा:

XADD myKey * field0 value1 field0 value2 field2 value3

सहसंबद्ध फ़ील्ड और मान भेजने के बजाय (field0 करने के लिए मान0 और इसी तरह)।

बाद में कोड में, मैं XREAD के परिणामों को एक लूप में मौजूदा PHP सरणी (जो सहयोगी है) में डाल रहा था, प्रत्येक फ़ील्ड को प्रत्येक मान के साथ एक कुंजी के रूप में असाइन कर रहा था और पहले से सेट कुछ भी छोड़ रहा था। तो, मैंने इस तरह की एक सरणी के साथ शुरुआत की:

array(1) {
  ["foo"]=>
  string(3) "bar"
}

और इस तरह एक सरणी के साथ समाप्त हुआ:

array(3) {
  ["foo"]=>
  string(3) "bar"
  ["field0"]=>
  string(6) "value1"
  ["field2"]=>
  string(6) "value3"
}

मैं समझ नहीं पा रहा था कि यह कैसे संभव है। मैं जल्दी से बग को ट्रैक करने में सक्षम था कि क्यों value1 field0 . को सौंपा गया (मेरे XADD में ऊपर उल्लिखित एक-एक त्रुटि), लेकिन field0 क्यों नहीं था value2 . के रूप में सेट करें ? एचएसईटी में, फ़ील्ड जोड़ने के लिए यह व्यवहार मूल रूप से अपरर्ट है - यदि कोई फ़ील्ड मौजूद है तो उसे अपडेट करें, अन्यथा फ़ील्ड जोड़ें और मान सेट करें।

MONITOR लॉग्स की जांच करने और मानों को फिर से चलाने के लिए, मैंने XREAD को निम्नानुसार चलाया:

> XREAD STREAMS myKey 0
1) 1) "myKey"
   2) 1) 1) "1592409586907-0"
         2) 1) "field0"
            2) "value1"
            3) "field0"
            4) "value2"
            5) "field2"
            6) "value3"

दोहराव मौजूद हैं और रिकॉर्ड किए गए हैं, अपरक्षित नहीं; इसके अतिरिक्त आदेश संरक्षित है यह हैश जैसा कुछ नहीं है!

JSON को एक सन्निकटन के रूप में उपयोग करने के बारे में सोचते हुए, मैंने सोचा कि स्ट्रीम प्रविष्टियाँ इस तरह दिखती हैं:

{
  "field1"  : "value",
  "field2"  : "value",
  "field3"  : "value"
}

लेकिन वे वास्तव में इस तरह दिखते हैं:

[
  ["field1", "value"],
  ["field2", "value"],
  ["field3", "value"]
]

इसका क्या अर्थ है?

खुशखबरी

यदि आपके पास कोड है जो वर्तमान में स्ट्रीम के साथ काम करता है और आप मान रहे हैं कि प्रविष्टियां हैश मैप्स की तरह हैं, तो आप शायद ठीक हैं। आपको डुप्लिकेट फ़ील्ड डालने के संबंध में संभावित बगों को देखने की आवश्यकता है, क्योंकि वे किसी दिए गए एप्लिकेशन में आपकी अपेक्षा के अनुरूप व्यवहार नहीं कर सकते हैं। यह हर परिस्थिति या क्लाइंट लाइब्रेरी में लागू नहीं हो सकता है, लेकिन एक अच्छा अभ्यास डेटा संरचना की आपूर्ति करना होगा जो दोहराव की अनुमति नहीं देता है (ऊपर देखें) और इसे XADD को आपूर्ति करते समय तर्कों में क्रमबद्ध करें। अद्वितीय फ़ील्ड अंदर और अद्वितीय फ़ील्ड बाहर।

बुरी खबर

सभी क्लाइंट लाइब्रेरी और टूल्स इसे सही नहीं पाते हैं। अपेक्षाकृत निम्न-स्तरीय क्लाइंट लाइब्रेरी (गैर-विस्तृत:नोड_रेडिस, हायररिस) रेडिस से आउटपुट को भाषा निर्माण में बदलने के लिए बहुत कुछ नहीं करते हैं। अन्य उच्च-स्तरीय पुस्तकालय करते हैं भाषा निर्माण में रेडिस की वास्तविक वापसी का सार-आपको यह देखने के लिए जांचना चाहिए कि आपकी पसंद की लाइब्रेरी ऐसा कर रही है या नहीं और यदि ऐसा होता है तो इसे एक समस्या में डाल दें। कुछ उच्च-स्तरीय पुस्तकालयों ने इसे शुरू से ही ठीक कर लिया है (stackexchange.redis), इसलिए यश वहाँ के कारण हैं।

दूसरा हिस्सा जो थोड़ा खराब है:यदि आप RESP3 के बहुत शुरुआती अपनाने वाले थे, तो आपने XREAD / XREADGROUP को RESP3 मानचित्र प्रकार लौटाने का अनुभव किया होगा। अप्रैल की शुरुआत तक, Redis 6 का अंडर-डेवलपमेंट संस्करण, स्ट्रीम्स को पढ़ते समय भ्रामक रूप से नक्शे लौटा रहा था। शुक्र है, इसका समाधान हो गया और रेडिस 6 का जीए संस्करण—पहली बार जब आपको वास्तव में उत्पादन में आरईएसपी3 का उपयोग करना चाहिए था—एक्सआरईएडी / एक्सरीडग्रुप के लिए उचित रिटर्न के साथ भेज दिया गया।

मज़ेदार हिस्सा

चूंकि मैं समझ चुका हूं कि आप शायद स्ट्रीम के बारे में कैसे गलत हैं, आइए इस बारे में थोड़ा सोचें कि आप इस पहले से गलत समझी गई संरचना का लाभ कैसे उठा सकते हैं।

स्ट्रीम प्रविष्टियों में ऑर्डर करने के लिए अर्थ अर्थ लागू करें

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

<polyline points="50,150 50,200 200,200 200,100">

इसे इस प्रकार व्यक्त किया जा सकता है:

> XADD mySVG * 50 150 50 200 200 200 200 100

प्रत्येक अतिरिक्त आकार उसी कुंजी पर एक और प्रविष्टि होगी। यदि आपने रेडिस हैश के साथ ऐसा कुछ करने का प्रयास किया है, तो आपके पास केवल दो निर्देशांक होंगे और कोई ऑर्डर गारंटी नहीं होगी। बेशक, आप इसे बिटफील्ड जैसी चीजों के साथ कर सकते हैं, लेकिन आप लंबाई और समन्वय आकार के संबंध में एक टन लचीलापन खो देंगे। स्ट्रीम के साथ, आप समय के साथ दिखाई देने वाली आकृतियों की एक श्रृंखला का प्रतिनिधित्व करने के लिए टाइमस्टैम्प के साथ कुछ साफ-सुथरा भी कर सकते हैं।

अनुक्रमित वस्तुओं का समय-क्रम सेट बनाएं

इसके लिए एक छोटे से हैक की आवश्यकता होती है, लेकिन यह बहुत अधिक कार्यक्षमता प्रदान कर सकता है। कल्पना कीजिए कि आप सरणियों जैसे डेटा का एक क्रम रख रहे हैं। प्रभावी रूप से, सरणियों की एक सरणी—JSON में आप सोच सकते हैं कि क्या यह कुछ ऐसा है:

[
  ["A New Hope", "The Empire Strikes Back", "Return of the Jedi"],
  ["The Phantom Menace", "Attack of the Clones", "Revenge of the Sith"],
  ["The Force Awakens", "The Last Jedi", "The Rise of Skywalker"]
]

आप इसे एक छोटी सी बारीकियों के साथ स्ट्रीम प्रविष्टियों की एक श्रृंखला के रूप में स्पष्ट कर सकते हैं:आपको यह सुनिश्चित करने की ज़रूरत है कि आपकी आंतरिक सूचियों में (छद्म) तत्वों की संख्या विषम नहीं है। यदि वे विषम हैं, जैसा कि ऊपर बताया गया है, तो आपको इसे किसी तरह रिकॉर्ड करना होगा—यहां बताया गया है कि मैं इसे एक खाली स्ट्रिंग के साथ कैसे कर रहा हूं:

> XADD starwars * "A New Hope" "The Empire Strikes Back" "Return of the Jedi" ""
"1592427370458-0"
> XADD starwars * "The Phantom Menace" "Attack of the Clones" "Revenge of the Sith" ""
"1592427393492-0"
> XADD starwars * "The Force Awakens" "The Last Jedi" "The Rise of Skywalker" ""
"1592427414475-0"
> XREAD streams starwars 0
1# "starwars" => 
   1) 1) "1592427370458-0"
      2) 1) "A New Hope"
         2) "The Empire Strikes Back"
         3) "Return of the Jedi"
         4) ""
   2) 1) "1592427393492-0"
      2) 1) "The Phantom Menace"
         2) "Attack of the Clones"
         3) "Revenge of the Sith"
         4) ""
   3) 1) "1592427414475-0"
      2) 1) "The Force Awakens"
         2) "The Last Jedi"
         3) "The Rise of Skywalker"
         4) ""

किसी भी 0-लंबाई वाले स्ट्रिंग्स को फ़िल्टर करने के (मामूली) खर्च पर आपको इस पैटर्न में बहुत कुछ मिलता है।

पेजिनेशन कैश के रूप में स्ट्रीम

एक मुश्किल चीज जो आप अक्सर देखते हैं वह है साइट पर वस्तुओं की एक सूची (ई-कॉमर्स, संदेश बोर्ड, आदि)। यह आमतौर पर कैश किया जाता है, लेकिन मैंने देखा है कि लोग इस प्रकार के डेटा को कैश करने के लिए सबसे अच्छी विधि खोजने की कोशिश कर रहे हैं - क्या आप पूरे परिणाम सेट को एक सॉर्ट किए गए सेट की तरह कैश करते हैं और ZRANGE के साथ बाहर की ओर पृष्ठांकित करते हैं, या क्या आप पूर्ण पृष्ठ संग्रहीत करते हैं स्ट्रिंग कुंजियों पर? दोनों तरीकों के फायदे और नुकसान हैं।

जैसा कि यह पता चला है, धाराएं वास्तव में इसके लिए काम करती हैं। उदाहरण के लिए, ई-कॉमर्स लिस्टिंग को लें। आपके पास आइटम की एक शृंखला है, प्रत्येक में एक आईडी है। उन वस्तुओं को एक सीमित श्रृंखला में सूचीबद्ध किया जाता है जिसमें आमतौर पर उलटा होता है (ए-जेड, जेड-ए, निम्न से उच्च, उच्च से निम्न, उच्चतम-से-निम्न रेटिंग, निम्नतम-से-उच्चतम रेटिंग, आदि)।

इस प्रकार के डेटा को एक स्ट्रीम में मॉडल करने के लिए, आप एक विशेष "चंक" आकार निर्धारित करेंगे और उसे एक प्रविष्टि बनाएंगे। एक प्रविष्टि में विखंडू और पूर्ण परिणाम पृष्ठ क्यों नहीं? यह आपको अपने पेजिनेशन में अलग-अलग आकार के पृष्ठ रखने की अनुमति देता है (उदाहरण के लिए प्रति पृष्ठ 10 आइटम 5 प्रत्येक के 2 भाग से बने हो सकते हैं, जबकि 25 प्रति पृष्ठ 5 प्रत्येक के 5 भाग होंगे)। प्रत्येक प्रविष्टि में वे फ़ील्ड होंगे जो उत्पाद आईडी से मैप करते हैं और मान उत्पाद डेटा होंगे। कृत्रिम रूप से कम चंक आकार के साथ इस सरलीकृत उदाहरण पर एक नज़र डालें:

आप शायद रेडिस स्ट्रीम के बारे में गलत सोच रहे हैं

जब आप कैश्ड मानों को पुनः प्राप्त करना चाहते हैं, तो आप XRANGE को COUNT तर्क के साथ चलाएंगे जो आपके इंटरफ़ेस के लिए परिणाम पृष्ठ बनाने वाले विखंडू की संख्या पर सेट है। इसलिए, यदि आप चार वस्तुओं का पहला पृष्ठ प्राप्त करना चाहते हैं तो आप चलाएंगे:

> XRANGE listcache - + COUNT 2
1) 1) "0-1"
   2) 1) "123"
      2) "{ \"Red Belt\", ... }"
      3) "456"
      4) "{ \"Yellow Belt\", ... }"
2) 1) "0-2"
   2) 1) "789"
      2) "{ \"Blue Belt\", ... }"
      3) "012"
      4) "{ \"Purple Belt\", ... }"

4 आइटमों का दूसरा पृष्ठ प्राप्त करने के लिए, आपको 1 से बढ़ी हुई निचली बाउंड स्ट्रीम आईडी प्रदान करनी होगी, हमारे मामले में, निचली सीमा 0-2 होगी

> XRANGE listcache 0-3 + COUNT 2
1) 1) "0-3"
   2) 1) "345"
      2) "{ \"Black Belt\", ... }"
      3) "678"
      4) "{ \"Red Boa\", ... }"
2) 1) "0-4"
   2) 1) "901"
      2) "{ \"Yellow Boa\", ... }"
      3) "234"
      4) "{ \"Green Belt\", ... }"

यह सॉर्ट किए गए सेट या सूचियों पर एक कम्प्यूटेशनल जटिलता लाभ प्रदान करता है क्योंकि इस उपयोग में XRANGE प्रभावी रूप से O(1) है, लेकिन ध्यान रखने योग्य कुछ बातें हैं:

  • XREVRANGE को उलटने के लिए इस्तेमाल किया जा सकता है, हालांकि यह केवल "हिस्सा" के क्रम को उलट देगा। प्रत्येक खंड के अंदर आपको एप्लिकेशन लॉजिक में क्रम को उलटना होगा जो अपेक्षाकृत तुच्छ होना चाहिए।
  • यदि आप मैन्युअल रूप से स्ट्रीम आईडी को रैखिक रूप से सेट करते हैं, तो सूची के विभिन्न भागों की तलाश करना "निःशुल्क" है, इसलिए खंड 1 स्ट्रीम आईडी है 0-1 , खंड 2 स्ट्रीम आईडी है 0-2 और इसी तरह। ध्यान दें कि आपको इसे 0 के बजाय 1 से शुरू करना होगा क्योंकि आप 0-0 पर स्ट्रीम प्रविष्टि नहीं जोड़ सकते हैं

किसी भी कुंजी की तरह, आप एक्सपायरी का उपयोग यह प्रबंधित करने के लिए कर सकते हैं कि स्ट्रीम कितनी देर तक रहती है। यह कैसे किया जा सकता है इसका एक उदाहरण स्ट्रीम-पंक्ति-कैश में है।

मुझे उम्मीद है कि यह पोस्ट आपको कुछ अतिरिक्त संदर्भ देती है कि स्ट्रीम वास्तव में कैसे काम करती है और आप अपने अनुप्रयोगों में स्ट्रीम के इन बड़े पैमाने पर अज्ञात गुणों का लाभ कैसे उठा सकते हैं।


  1. आप संभवतः iPhone कैश को गलत तरीके से साफ़ कर रहे हैं - इसे सही तरीके से करने का तरीका यहां दिया गया है

    यदि आप एक iPhone उपयोगकर्ता हैं, तो iPhone पर कैश साफ़ करना आपके लिए बहुत मायने नहीं रख सकता है या नहीं भी हो सकता है क्योंकि iOS प्रति मेमोरी को प्रबंधित करने में पर्याप्त कुशल है। लेकिन, यहां तथ्य यह है - यह केवल ऐप नहीं है जो आपके आईफोन या आईपैड पर जगह लेता है, यह कैश भी हो सकता है जो आपके डिवाइ

  1. PUBG के बारे में 11 तथ्य जो शायद आप नहीं जानते

    PlayerUnogns Battlegrounds या PUBG एक ऐसा नाम नहीं है जिसे किसी प्रकार के परिचय की आवश्यकता है। और खेल नियंत्रण और इसमें उत्कृष्टता प्राप्त करने की तरकीबों के बारे में शायद ही कुछ ऐसा है जो पेशेवर खिलाड़ियों ने अभी तक छानबीन नहीं की है। पिछले ढाई साल से PUBG के शानदार दौर में, खिलाड़ियों ने उच्च श्र

  1. Facebook के ऐसे ट्रिक्स जिनके बारे में आप शायद नहीं जानते

    फेसबुक इन दिनों हमारी दिनचर्या का हिस्सा है। हर किसी का अपने फेसबुक अकाउंट को इस्तेमाल करने का तरीका अलग होता है। कुछ लोग इसका इस्तेमाल बिजनेस के लिए करते हैं तो कुछ लोग इसका इस्तेमाल दोस्तों से जुड़ने के लिए करते हैं। अपने फेसबुक अकाउंट का उपयोग करते समय हमें कई अतिरिक्त सुविधाओं की आवश्यकता का एहस