इलास्टिकसर्च अपाचे ल्यूसीन पर आधारित एक ओपन-सोर्स सर्च और एनालिटिक्स इंजन है। इलास्टिकसर्च का उपयोग करके परिवर्तन डेटा कैप्चर (सीडीसी) डेटा पर एप्लिकेशन बनाते समय, आप इंडेक्स में मौजूदा दस्तावेज़ों में लगातार अपडेट या संशोधनों को संभालने के लिए सिस्टम को आर्किटेक्ट करना चाहेंगे।
इस ब्लॉग में, हम अपडेट के लिए उपलब्ध विभिन्न विकल्पों के बारे में जानेंगे, जिसमें पूर्ण अपडेट, आंशिक अपडेट और स्क्रिप्टेड अपडेट शामिल हैं। हम यह भी चर्चा करेंगे कि दस्तावेज़ को संशोधित करते समय Elasticsearch में क्या होता है और लगातार अपडेट सिस्टम में CPU उपयोग को कैसे प्रभावित करते हैं।
लगातार अपडेट होने वाले उपयोग के मामलों को बेहतर ढंग से समझने के लिए, आइए नेटफ्लिक्स जैसी वीडियो स्ट्रीमिंग सेवा के लिए एक खोज एप्लिकेशन देखें। जब कोई उपयोगकर्ता किसी शो, यानी “राजनीतिक थ्रिलर” की खोज करता है, तो उन्हें कीवर्ड और अन्य मेटाडेटा के आधार पर प्रासंगिक परिणामों का एक सेट लौटाया जाता है।
आइए Elasticsearch में शो “हाउस ऑफ कार्ड्स” के एक उदाहरण दस्तावेज़ को देखें:
{ "name": "House of Cards", "description": "Frank Underwood is a Democrat appointed as the Secretary of State. Along with his wife, he sets out on a quest to seek revenge from the people who betrayed him while successfully rising to supremacy.", "genres": ["drama", "thriller"], "views": 100, }
खोज को इलास्टिकसर्च में name
और description
पूर्ण-पाठ खोज फ़ील्ड के रूप में उपयोग करने के लिए कॉन्फ़िगर किया जा सकता है। views
फ़ील्ड, जो प्रति शीर्षक व्यूज़ की संख्या संग्रहीत करता है, का उपयोग सामग्री को बढ़ावा देने, अधिक लोकप्रिय शो को उच्च रैंकिंग देने के लिए किया जा सकता है। जब भी कोई उपयोगकर्ता किसी शो या मूवी का एपिसोड देखता है, तो views
फ़ील्ड में वृद्धि होती है।
नेटफ्लिक्स के स्केल पर किसी एप्लिकेशन में इस सर्च कॉन्फ़िगरेशन का उपयोग करते समय, किए गए अपडेट की संख्या नेटफ्लिक्स एंगेजमेंट रिपोर्ट द्वारा निर्धारित अनुसार आसानी से प्रति मिनट लाखों को पार कर सकती है। रिपोर्ट के अनुसार, जनवरी से जुलाई तक उपयोगकर्ताओं ने ~100 बिलियन घंटे की सामग्री देखी। प्रति एपिसोड या मूवी को देखने का औसत समय 15 मिनट मानते हुए, प्रति मिनट व्यू की संख्या औसतन 1.3 मिलियन तक पहुँच जाती है। ऊपर निर्दिष्ट सर्च कॉन्फ़िगरेशन के साथ, प्रत्येक व्यू को लाखों स्केल में अपडेट की आवश्यकता होगी।
कई खोज और विश्लेषण अनुप्रयोगों को लगातार अपडेट का अनुभव हो सकता है, खासकर जब वे CDC डेटा पर आधारित हों।
आइए नीचे दिए गए कोड के साथ Elasticsearch में अपडेट करने के सामान्य उदाहरण पर गौर करें:
- from elasticsearch import Elasticsearch # Connect to your Elasticsearch instance es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID you want to update index_name = 'movies' document_id = 'your_document_id' # Retrieve the current document to get the current 'views' value try: current_doc = es.get(index=index_name, id=document_id) current_views = current_doc['_source']['views'] except Exception as e: print(f"Error retrieving current document: {e}") current_views = 0 # Set a default value if there's an error # Define the update body to increment 'views' by 1 update_body = { "doc": { "views": current_views + 1 # Increment 'views' by 1 } } # Perform the update try: es.update(index=index_name, id=document_id, body=update_body) print("Document updated successfully!") except Exception as e: print(f"Error updating document: {e}")
इलास्टिक्सर्च में अपडेट करते समय, आप किसी मौजूदा दस्तावेज़ को बदलने के लिए इंडेक्स एपीआई का उपयोग कर सकते हैं या किसी दस्तावेज़ में आंशिक अपडेट करने के लिए अपडेट एपीआई का उपयोग कर सकते हैं।
इंडेक्स एपीआई पूरे दस्तावेज़ को पुनः प्राप्त करता है, दस्तावेज़ में परिवर्तन करता है, और फिर दस्तावेज़ को पुनः अनुक्रमित करता है। अपडेट एपीआई के साथ, आप पूरे दस्तावेज़ के बजाय केवल उन फ़ील्ड को भेजते हैं जिन्हें आप संशोधित करना चाहते हैं। इसके परिणामस्वरूप दस्तावेज़ को फिर से अनुक्रमित किया जाता है, लेकिन नेटवर्क पर भेजे जाने वाले डेटा की मात्रा कम हो जाती है। अपडेट एपीआई विशेष रूप से उन मामलों में उपयोगी है जहां दस्तावेज़ का आकार बड़ा है और पूरे दस्तावेज़ को नेटवर्क पर भेजना समय लेने वाला होगा।
आइए देखें कि इंडेक्स एपीआई और अपडेट एपीआई दोनों पायथन कोड का उपयोग करके कैसे काम करते हैं।
from elasticsearch import Elasticsearch # Connect to Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID index_name = "your_index" document_id = "1" # Retrieve the existing document existing_document = es.get(index=index_name, id=document_id) # Make your changes to the document existing_document["_source"]["field1"] = "new_value1" existing_document["_source"]["field2"] = "new_value2" # Call the index API to perform the full update es.index(index=index_name, id=document_id, body=existing_document["_source"])
जैसा कि आप ऊपर दिए गए कोड में देख सकते हैं, इंडेक्स एपीआई को इलास्टिकसर्च के लिए दो अलग-अलग कॉल की आवश्यकता होती है, जिसके परिणामस्वरूप आपके क्लस्टर पर धीमी गति से प्रदर्शन और अधिक लोड हो सकता है।
आंशिक अद्यतन आंतरिक रूप से रीइंडेक्स एपीआई का उपयोग करते हैं, लेकिन बेहतर प्रदर्शन के लिए केवल एक नेटवर्क कॉल की आवश्यकता के लिए कॉन्फ़िगर किया गया है।
from elasticsearch import Elasticsearch # Connect to Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID index_name = "your_index" document_id = "1" # Specify the fields to be updated update_fields = { "field1": "new_value1", "field2": "new_value2" } # Use the update API to perform a partial update es.update(index=index_name, id=document_id, body={"doc": update_fields})
आप व्यू काउंट को अपडेट करने के लिए Elasticsearch में अपडेट API का उपयोग कर सकते हैं, लेकिन अपडेट API का उपयोग पिछले मान के आधार पर व्यू काउंट को बढ़ाने के लिए नहीं किया जा सकता है। ऐसा इसलिए है क्योंकि हमें नया व्यू काउंट मान सेट करने के लिए पुराने व्यू काउंट की आवश्यकता होती है।
आइए देखें कि हम एक शक्तिशाली स्क्रिप्टिंग भाषा, पेनलेस का उपयोग करके इसे कैसे ठीक कर सकते हैं।
पेनलेस एक स्क्रिप्टिंग भाषा है जिसे इलास्टिकसर्च के लिए डिज़ाइन किया गया है और इसका उपयोग क्वेरी और एकत्रीकरण गणना, जटिल शर्तों, डेटा रूपांतरण और बहुत कुछ के लिए किया जा सकता है। पेनलेस जटिल तर्क के आधार पर दस्तावेज़ों को संशोधित करने के लिए अपडेट क्वेरी में स्क्रिप्ट के उपयोग को भी सक्षम बनाता है।
नीचे दिए गए उदाहरण में, हम एक एकल API कॉल में अपडेट करने के लिए पेनलेस स्क्रिप्ट का उपयोग करते हैं और पुराने दृश्य गणना के मान के आधार पर नए दृश्य गणना में वृद्धि करते हैं।
from elasticsearch import Elasticsearch # Connect to your Elasticsearch instance es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID you want to update index_name = 'movies' document_id = 'your_document_id' # Define the Painless script for the update update_script = { "script": { "lang": "painless", "source": "ctx._source.views += 1" # Increment 'views' by 1 } } # Perform the update using the Painless script try: es.update(index=index_name, id=document_id, body=update_script) print("Document updated successfully!") except Exception as e: print(f"Error updating document: {e}")
पेनलेस स्क्रिप्ट को समझना बहुत आसान है, यह प्रत्येक दस्तावेज़ के लिए व्यू काउंट को 1 से बढ़ा देता है।
इलास्टिकसर्च में नेस्टेड ऑब्जेक्ट एक डेटा संरचना है जो एक ही पैरेंट दस्तावेज़ के भीतर अलग-अलग दस्तावेज़ों के रूप में ऑब्जेक्ट की सरणी को अनुक्रमित करने की अनुमति देता है। नेस्टेड ऑब्जेक्ट जटिल डेटा से निपटने के दौरान उपयोगी होते हैं जो स्वाभाविक रूप से एक नेस्टेड संरचना बनाते हैं, जैसे ऑब्जेक्ट के भीतर ऑब्जेक्ट। एक सामान्य इलास्टिकसर्च दस्तावेज़ में, ऑब्जेक्ट की सरणी समतल होती है, लेकिन नेस्टेड डेटा प्रकार का उपयोग करने से सरणी में प्रत्येक ऑब्जेक्ट को स्वतंत्र रूप से अनुक्रमित और क्वेरी किया जा सकता है।
एलास्टिकसर्च में नेस्टेड ऑब्जेक्ट्स को अपडेट करने के लिए पेनलेस स्क्रिप्ट का भी उपयोग किया जा सकता है।
from elasticsearch import Elasticsearch # Connect to your Elasticsearch instance es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID for the example index_name = 'your_index' document_id = 'your_document_id' # Specify the nested field and the updated value nested_field = "nested_field_name" updated_value = "new_value" # Define the Painless script for the update update_script = { "script": { "lang": "painless", "source": "ctx._source.nested_field_name = params.updated_value", "params": { "updated_value": updated_value } } } # Perform the update using the Update API and the Painless script try: es.update(index=index_name, id=document_id, body=update_script) print("Nested object updated successfully!") except Exception as e: print(f"Error updating nested object: {e}")
एलास्टिकसर्च में किसी दस्तावेज़ में नया फ़ील्ड जोड़ना इंडेक्स ऑपरेशन के माध्यम से पूरा किया जा सकता है।
आप अपडेट एपीआई का उपयोग करके किसी मौजूदा दस्तावेज़ को नए फ़ील्ड के साथ आंशिक रूप से अपडेट कर सकते हैं। जब इंडेक्स पर डायनेमिक मैपिंग सक्षम होती है, तो नया फ़ील्ड शुरू करना सीधा-सादा होता है। बस उस फ़ील्ड वाले दस्तावेज़ को इंडेक्स करें और इलास्टिकसर्च अपने आप उपयुक्त मैपिंग का पता लगा लेगा और मैपिंग में नया फ़ील्ड जोड़ देगा।
इंडेक्स पर डायनेमिक मैपिंग अक्षम होने पर, आपको अपडेट मैपिंग API का उपयोग करना होगा। आप मूवी इंडेक्स में “श्रेणी” फ़ील्ड जोड़कर इंडेक्स मैपिंग को अपडेट करने का एक उदाहरण नीचे देख सकते हैं।
PUT /movies/_mapping { "properties": { "category": { "type": "keyword" } } }
जबकि कोड सरल है, Elasticsearch आंतरिक रूप से इन अपडेट को करने के लिए बहुत अधिक काम कर रहा है क्योंकि डेटा अपरिवर्तनीय खंडों में संग्रहीत है। नतीजतन, Elasticsearch किसी दस्तावेज़ में केवल इन-प्लेस अपडेट नहीं कर सकता है। अपडेट करने का एकमात्र तरीका पूरे दस्तावेज़ को फिर से अनुक्रमित करना है, चाहे कोई भी API इस्तेमाल किया गया हो।
इलास्टिकसर्च हुड के नीचे अपाचे ल्यूसीन का उपयोग करता है। ल्यूसीन इंडेक्स एक या अधिक खंडों से बना होता है। एक खंड एक स्व-निहित, अपरिवर्तनीय सूचकांक संरचना है जो समग्र सूचकांक के सबसेट का प्रतिनिधित्व करता है। जब दस्तावेज़ जोड़े जाते हैं या अपडेट किए जाते हैं, तो नए ल्यूसीन सेगमेंट बनाए जाते हैं और पुराने दस्तावेज़ों को सॉफ्ट डिलीट के लिए चिह्नित किया जाता है। समय के साथ, जैसे-जैसे नए दस्तावेज़ जोड़े जाते हैं या मौजूदा अपडेट किए जाते हैं, कई सेगमेंट जमा हो सकते हैं। इंडेक्स संरचना को अनुकूलित करने के लिए, ल्यूसीन समय-समय पर छोटे खंडों को बड़े खंडों में मिलाता है।
चूंकि प्रत्येक अद्यतन ऑपरेशन एक पुनः अनुक्रमण ऑपरेशन है, इसलिए सभी अद्यतन अनिवार्यतः सॉफ्ट डिलीट के साथ सम्मिलित होते हैं।
अपडेट को इंसर्ट ऑपरेशन के रूप में मानने पर लागत संबंधी प्रभाव पड़ता है। एक तरफ, डेटा के सॉफ्ट डिलीट का मतलब है कि पुराना डेटा अभी भी कुछ समय के लिए बरकरार रखा जा रहा है, जिससे इंडेक्स का स्टोरेज और मेमोरी बढ़ जाती है। सॉफ्ट डिलीट, रीइंडेक्सिंग और कचरा संग्रहण ऑपरेशन करने से CPU पर भी भारी बोझ पड़ता है, यह बोझ सभी प्रतिकृतियों पर इन ऑपरेशनों को दोहराने से और भी बढ़ जाता है।
जैसे-जैसे आपका उत्पाद बढ़ता है और आपका डेटा समय के साथ बदलता है, अपडेट करना और भी मुश्किल हो सकता है। Elasticsearch को परफ़ॉर्मेंस देने के लिए, आपको अपने क्लस्टर में शार्ड, एनालाइज़र और टोकनाइज़र को अपडेट करना होगा, जिसके लिए पूरे क्लस्टर को फिर से इंडेक्स करना होगा। उत्पादन अनुप्रयोगों के लिए, इसके लिए एक नया क्लस्टर सेट करना होगा और सभी डेटा को माइग्रेट करना होगा। क्लस्टर को माइग्रेट करना समय लेने वाला और त्रुटिपूर्ण दोनों है, इसलिए इसे हल्के में नहीं लिया जाना चाहिए।
Elasticsearch में अपडेट ऑपरेशन की सरलता सिस्टम के हुड के नीचे हो रहे भारी परिचालन कार्यों को छिपा सकती है। Elasticsearch प्रत्येक अपडेट को एक इन्सर्ट के रूप में मानता है, जिसके लिए पूरे दस्तावेज़ को फिर से बनाने और फिर से अनुक्रमित करने की आवश्यकता होती है। लगातार अपडेट वाले अनुप्रयोगों के लिए, यह जल्दी से महंगा हो सकता है जैसा कि हमने नेटफ्लिक्स के उदाहरण में देखा था जहाँ हर मिनट लाखों अपडेट होते हैं। हम या तो बल्क एपीआई का उपयोग करके बैच अपडेट की सलाह देते हैं, जो आपके कार्यभार में विलंबता जोड़ता है, या Elasticsearch में लगातार अपडेट का सामना करने पर वैकल्पिक समाधानों को देखता है।
रॉकसेट, क्लाउड में निर्मित एक खोज और विश्लेषण डेटाबेस, इलास्टिकसर्च का एक परिवर्तनशील विकल्प है। रॉक्सडीबी पर निर्मित होने के कारण, एक कुंजी-मूल्य स्टोर जो अपनी परिवर्तनशीलता के लिए लोकप्रिय है, रॉकसेट दस्तावेजों में इन-प्लेस अपडेट कर सकता है। इसका परिणाम यह होता है कि पूरे दस्तावेज़ के बजाय केवल व्यक्तिगत फ़ील्ड का मान अपडेट और पुनः अनुक्रमित किया जाता है।
यदि आप अद्यतन-भारी कार्यभार के लिए इलास्टिक्सर्च और रॉकसेट के प्रदर्शन की तुलना करना चाहते हैं, तो आप 300 डॉलर के क्रेडिट के साथ रॉकसेट का निःशुल्क परीक्षण शुरू कर सकते हैं।