etcd बनाम PostgreSQL
Jinhua Luo
March 17, 2023
ऐतिहासिक पृष्ठभूमि
PostgreSQL
PostgreSQL को मूल रूप से 1986 में कैलिफोर्निया विश्वविद्यालय, बर्कले में प्रोफेसर माइकल स्टोनब्रैकर के नेतृत्व में विकसित किया गया था। कई दशकों के विकास के दौरान, PostgreSQL आज उपलब्ध प्रमुख ओपन-सोर्स रिलेशनल डेटाबेस प्रबंधन प्रणाली के रूप में उभरा है। इसका अनुमति देने वाला लाइसेंस किसी को भी PostgreSQL का उपयोग, संशोधन और वितरण करने की अनुमति देता है, चाहे वह निजी, वाणिज्यिक या शैक्षणिक अनुसंधान उद्देश्यों के लिए हो।
PostgreSQL ऑनलाइन विश्लेषणात्मक प्रसंस्करण (OLAP) और ऑनलाइन लेनदेन प्रसंस्करण (OLTP) दोनों के लिए मजबूत समर्थन प्रदान करता है, जिसमें शक्तिशाली SQL क्वेरी क्षमताएं और विस्तार की एक विस्तृत श्रृंखला शामिल है जो इसे लगभग सभी वाणिज्यिक आवश्यकताओं को पूरा करने की अनुमति देती है। परिणामस्वरूप, हाल के वर्षों में इस पर अधिक ध्यान दिया गया है। वास्तव में, PostgreSQL की स्केलेबिलिटी और उच्च प्रदर्शन इसे किसी भी अन्य प्रकार के डेटाबेस की कार्यक्षमता को दोहराने में सक्षम बनाता है।
छवि स्रोत (CC 3.0 BY-SA लाइसेंस समझौते का पालन करते हुए): https://en.wikibooks.org/wiki/PostgreSQL/Architecture
etcd
etcd कैसे अस्तित्व में आया, और यह किस समस्या का समाधान करता है?
2013 में, स्टार्टअप टीम CoreOS ने Container Linux नामक एक उत्पाद विकसित किया। यह एक ओपन-सोर्स, हल्का ऑपरेटिंग सिस्टम है जो एप्लिकेशन सेवाओं के स्वचालन और तेजी से तैनाती को प्राथमिकता देता है। Container Linux को एप्लिकेशन को कंटेनर में चलाने की आवश्यकता होती है और यह एक क्लस्टर प्रबंधन समाधान प्रदान करता है, जिससे उपयोगकर्ताओं के लिए सेवाओं को एकल मशीन की तरह प्रबंधित करना सुविधाजनक हो जाता है।
यह सुनिश्चित करने के लिए कि उपयोगकर्ता सेवाएं नोड रीस्टार्ट के कारण डाउनटाइम का अनुभव न करें, CoreOS को कई प्रतिकृतियां चलाने की आवश्यकता थी। लेकिन कई प्रतिकृतियों के बीच समन्वय कैसे किया जाए और परिवर्तनों के दौरान सभी प्रतिकृतियां अनुपलब्ध होने से कैसे बचा जाए?
इस समस्या का समाधान करने के लिए, CoreOS टीम को एक समन्वय सेवा की आवश्यकता थी जो सेवा कॉन्फ़िगरेशन जानकारी संग्रहीत कर सके और वितरित लॉक क्षमताएं प्रदान कर सके, और भी बहुत कुछ। तो, उनका दृष्टिकोण क्या था? उन्होंने पहले व्यावसायिक परिदृश्य, दर्द बिंदुओं और मुख्य उद्देश्यों का विश्लेषण किया। फिर, उन्होंने अपने लक्ष्यों के अनुरूप एक समाधान चुना, यह मूल्यांकन करते हुए कि क्या एक ओपन-सोर्स समुदाय समाधान चुनना है या अपना स्वयं का कस्टम टूल विकसित करना है। यह दृष्टिकोण एक सार्वभौमिक समस्या-समाधान विधि है जो अक्सर चुनौतीपूर्ण समस्याओं का सामना करने पर अपनाई जाती है, और CoreOS टीम ने भी इसी सिद्धांत का पालन किया।
एक समन्वय सेवा को आदर्श रूप से निम्नलिखित पांच लक्ष्यों को पूरा करने की आवश्यकता होती है:
- कई डेटा प्रतिकृतियों के साथ उच्च उपलब्धता
- प्रतिकृतियों के बीच संस्करण जांच के साथ डेटा स्थिरता
- न्यूनतम संग्रहण क्षमता: समन्वय सेवा को केवल सेवाओं और नोड्स के लिए महत्वपूर्ण मेटाडेटा कॉन्फ़िगरेशन जानकारी संग्रहीत करनी चाहिए, न कि उपयोगकर्ता से संबंधित डेटा। यह दृष्टिकोण संग्रहण के लिए डेटा शार्डिंग की आवश्यकता को कम करता है और अत्यधिक डिजाइन से बचता है।
- CRUD (बनाना, पढ़ना, अद्यतन करना और हटाना) के लिए कार्यक्षमता, साथ ही डेटा परिवर्तनों को सुनने के लिए एक तंत्र। इसे सेवाओं की स्थिति जानकारी संग्रहीत करनी चाहिए, और जब सेवाओं में परिवर्तन या असामान्यताएं होती हैं, तो इसे परिवर्तन घटना को नियंत्रण तल पर तेजी से पुश करना चाहिए। यह सेवा उपलब्धता में सुधार करने और समन्वय सेवा के लिए अनावश्यक प्रदर्शन ओवरहेड को कम करने में मदद करता है।
- संचालन सरलता: समन्वय सेवा को संचालित, रखरखाव और समस्या निवारण में आसान होना चाहिए। एक उपयोग में आसान इंटरफेस त्रुटियों के जोखिम को कम कर सकता है, रखरखाव लागत को कम कर सकता है और डाउनटाइम को कम कर सकता है।
CAP प्रमेय के दृष्टिकोण से, etcd CP (स्थिरता और विभाजन सहनशीलता) प्रणाली से संबंधित है।

Kubernetes क्लस्टर के केंद्रीय घटक के रूप में, kube-apiserver अपने अंतर्निहित संग्रहण के लिए etcd का उपयोग करता है।
एक ओर, etcd का उपयोग k8s क्लस्टर में संसाधन वस्तुओं को बनाने में स्थायित्व के लिए किया जाता है। दूसरी ओर, यह etcd का डेटा वॉच तंत्र है जो पूरे क्लस्टर के Informer कार्य को संचालित करता है, जिससे निरंतर कंटेनर ऑर्केस्ट्रेशन सक्षम होता है।
इसलिए, तकनीकी दृष्टिकोण से, Kubernetes द्वारा etcd का उपयोग करने के मुख्य कारण हैं:
- etcd Go भाषा में लिखा गया है, जो k8s तकनीकी स्टैक के साथ संगत है, कम संसाधन खपत करता है, और तैनात करने में बेहद आसान है।
- etcd की मजबूत स्थिरता, वॉच, लीज़ और अन्य विशेषताएं k8s की मुख्य निर्भरताएं हैं।
संक्षेप में, etcd एक वितरित कुंजी-मूल्य डेटाबेस है जो विशेष रूप से कॉन्फ़िगरेशन प्रबंधन और वितरण के लिए डिज़ाइन किया गया है। एक क्लाउड-नेटिव सॉफ्टवेयर के रूप में, यह बॉक्स से बाहर उपयोग करने योग्य और उच्च प्रदर्शन प्रदान करता है, जो इसे इस विशिष्ट आवश्यकता के क्षेत्र में पारंपरिक डेटाबेस से बेहतर बनाता है।
etcd और PostgreSQL के बीच एक वस्तुनिष्ठ तुलना करने के लिए, जो दो अलग-अलग प्रकार के डेटाबेस हैं, उन्हें एक ही आवश्यकता के संदर्भ में मूल्यांकन करना महत्वपूर्ण है। इसलिए, यह लेख केवल कॉन्फ़िगरेशन प्रबंधन की आवश्यकताओं को पूरा करने की उनकी क्षमता के संदर्भ में दोनों के बीच के अंतर पर चर्चा करेगा।
डेटा मॉडल
विभिन्न डेटाबेस में उपयोगकर्ताओं को प्रस्तुत करने के लिए अलग-अलग डेटा मॉडल होते हैं, और यह कारक विभिन्न परिदृश्यों के लिए डेटाबेस की उपयुक्तता निर्धारित करता है।
कुंजी-मूल्य बनाम SQL
कुंजी-मूल्य डेटा मॉडल NoSQL में एक लोकप्रिय मॉडल है, जिसे etcd द्वारा भी अपनाया गया है। यह मॉडल SQL की तुलना में कैसे है और इसके क्या फायदे हैं?
पहले, SQL पर एक नज़र डालते हैं।
रिलेशनल डेटाबेस डेटा को टेबल में बनाए रखते हैं और संरचित जानकारी को संग्रहीत और एक्सेस करने के लिए एक कुशल, सहज और लचीला तरीका प्रदान करते हैं।
एक टेबल, जिसे संबंध के रूप में भी जाना जाता है, कॉलम से बना होता है जिसमें डेटा की एक या अधिक श्रेणियां होती हैं, और पंक्तियां, जिन्हें टेबल रिकॉर्ड के रूप में भी जाना जाता है, जिसमें डेटा की श्रेणियों को परिभाषित करने वाले डेटा का एक सेट होता है। एप्लिकेशन डेटा को क्वेरी का उपयोग करके पुनः प्राप्त करते हैं जो "प्रोजेक्ट" जैसे ऑपरेशन का उपयोग करते हैं ताकि विशेषताओं की पहचान की जा सके, "चयन" टुपल्स की पहचान करने के लिए, और "जॉइन" संबंधों को संयोजित करने के लिए। डेटाबेस प्रबंधन के लिए रिलेशनल मॉडल 1970 में IBM के कंप्यूटर वैज्ञानिक एडगर कोड द्वारा विकसित किया गया था।

छवि स्रोत (CC 3.0 BY-SA लाइसेंस समझौते का पालन करते हुए): https://en.wikipedia.org/wiki/Associative_entity
टेबल में रिकॉर्ड के पास अद्वितीय पहचानकर्ता नहीं होते हैं क्योंकि टेबल को कई डुप्लिकेट पंक्तियों को समायोजित करने के लिए डिज़ाइन किया गया है। कुंजी-मूल्य क्वेरी को सक्षम करने के लिए, टेबल में कुंजी के रूप में कार्य करने वाले फ़ील्ड में एक अद्वितीय इंडेक्स जोड़ा जाना चाहिए। PostgreSQL का डिफ़ॉल्ट इंडेक्स btree है, जो etcd की तरह, कुंजियों पर रेंज क्वेरी कर सकता है।
संरचित क्वेरी भाषा (SQL) एक प्रोग्रामिंग भाषा है जो रिलेशनल डेटाबेस में जानकारी को संग्रहीत और प्रसंस्कृत करने के लिए है। एक रिलेशनल डेटाबेस जानकारी को सारणीबद्ध रूप में संग्रहीत करता है, जहां पंक्तियां और कॉलम विभिन्न डेटा विशेषताओं और डेटा मूल्यों के बीच विभिन्न संबंधों का प्रतिनिधित्व करते हैं। आप डेटाबेस से जानकारी को संग्रहीत, अद्यतन, हटाने, खोजने और पुनः प्राप्त करने के लिए SQL स्टेटमेंट का उपयोग कर सकते हैं। आप डेटाबेस प्रदर्शन को बनाए रखने और अनुकूलित करने के लिए SQL का भी उपयोग कर सकते हैं।
PostgreSQL ने SQL को कई एक्सटेंशन के साथ विस्तारित किया है, जिससे यह एक ट्यूरिंग-पूर्ण भाषा बन गई है। इसका मतलब है कि SQL किसी भी जटिल ऑपरेशन को कर सकता है, जो डेटा प्रसंस्करण तर्क को पूरी तरह से सर्वर साइड पर निष्पादित करने की सुविधा प्रदान करता है।
तुलना में, etcd को एक कॉन्फ़िगरेशन प्रबंधन टूल के रूप में डिज़ाइन किया गया है, जहां कॉन्फ़िगरेशन डेटा को आमतौर पर एक हैश टेबल के रूप में दर्शाया जाता है। यही कारण है कि इसका डेटा मॉडल कुंजी-मूल्य प्रारूप में संरचित है, जो प्रभावी रूप से एक बड़ी वैश्विक टेबल बनाता है। इस टेबल पर CRUD ऑपरेशन किए जा सकते हैं, जिसमें केवल दो फ़ील्ड होते हैं: एक अद्वितीय कुंजी जिसमें संस्करण जानकारी होती है, और एक अनटाइप्ड मूल्य। परिणामस्वरूप, क्लाइंट को आगे प्रसंस्करण के लिए पूर्ण मूल्य पुनः प्राप्त करना होगा।
कुल मिलाकर, etcd की कुंजी-मूल्य संरचना SQL को सरल बनाती है और कॉन्फ़िगरेशन प्रबंधन के विशिष्ट कार्य के लिए अधिक सुविधाजनक और सहज है।
MVCC (मल्टी-वर्जन कंकरेंसी कंट्रोल)
MVCC कॉन्फ़िगरेशन प्रबंधन में डेटा को संस्करणित करने के लिए एक आवश्यक विशेषता है। यह निम्नलिखित की अनुमति देता है:
- ऐतिहासिक डेटा को क्वेरी करना
- संस्करणों की तुलना करके डेटा की आयु निर्धारित करना
- डेटा को देखना, जिसके लिए संस्करणित करने की आवश्यकता होती है ताकि वृद्धिशील सूचनाएं सक्षम हो सकें
etcd और PostgreSQL दोनों में MVCC है, लेकिन उनके बीच क्या अंतर हैं?
etcd अपने MVCC सिस्टम को प्रबंधित करने के लिए एक वैश्विक रूप से बढ़ने वाले 64-बिट संस्करण काउंटर का उपयोग करता है। ओवरफ्लो की चिंता करने की आवश्यकता नहीं है। काउंटर को बड़ी संख्या में अपडेट को संभालने के लिए डिज़ाइन किया गया है, भले ही वे प्रति सेकंड लाखों की दर से होते हों। हर बार जब एक कुंजी-मूल्य जोड़ी बनाई या अद्यतन की जाती है, तो इसे एक संस्करण संख्या सौंपी जाती है। जब एक कुंजी-मूल्य जोड़ी हटाई जाती है, तो एक टॉम्बस्टोन बनाया जाता है जिसमें संस्करण संख्या 0 पर रीसेट हो जाती है। इसका मतलब है कि हर परिवर्तन एक नया संस्करण उत्पन्न करता है, न कि पिछले संस्करण को ओवरराइट करता है।
इसके अलावा, etcd एक कुंजी-मूल्य जोड़ी के सभी संस्करणों को बनाए रखता है और उन्हें उपयोगकर्ताओं के लिए दृश्यमान बनाता है। कुंजी-मूल्य डेटा को कभी भी ओवरराइट नहीं किया जाता है, और नए संस्करण मौजूदा संस्करणों के साथ संग्रहीत किए जाते हैं। etcd में MVCC कार्यान्वयन पढ़ने-लिखने के अलगाव को भी प्रदान करता है, जो उपयोगकर्ताओं को लॉक किए बिना डेटा पढ़ने की अनुमति देता है, जिससे यह पढ़ने-गहन उपयोग के मामलों के लिए उपयुक्त होता है।
PostgreSQL का MVCC कार्यान्वयन etcd से इस मायने में भिन्न है कि यह बढ़ते संस्करण संख्या प्रदान करने पर केंद्रित नहीं है, बल्कि लेनदेन और विभिन्न अलगाव स्तरों को उपयोगकर्ता के लिए पारदर्शी रूप से लागू करने पर केंद्रित है। MVCC एक आशावादी लॉकिंग तंत्र है जो समवर्ती अपडेट को सक्षम बनाता है। टेबल में प्रत्येक पंक्ति में एक लेनदेन ID रिकॉर्ड होता है, जहां xmin पंक्ति निर्माण के लेनदेन ID का प्रतिनिधित्व करता है और xmax पंक्ति अद्यतन के लेनदेन ID का प्रतिनिधित्व करता है।
- लेनदेन केवल उन डेटा को पढ़ सकते हैं जो उनसे पहले पहले ही प्रतिबद्ध हो चुके हैं।
- डेटा को अद्यतन करते समय, यदि एक संस्करण संघर्ष का सामना करना पड़ता है, तो PostgreSQL एक मिलान तंत्र के साथ पुनः प्रयास करेगा ताकि यह निर्धारित किया जा सके कि अद्यतन आगे बढ़ना चाहिए या नहीं।
एक उदाहरण देखने के लिए, कृपया निम्नलिखित लिंक देखें: https://devcenter.heroku.com/articles/postgresql-concurrency
दुर्भाग्य से, PostgreSQL में कॉन्फ़िगरेशन डेटा के लिए संस्करण नियंत्रण के लिए लेनदेन ID का उपयोग करना कई कारणों से संभव नहीं है:
- लेनदेन ID को एक ही लेनदेन में शामिल सभी पंक्तियों को सौंपा जाता है, जिसका अर्थ है कि संस्करण नियंत्रण पंक्ति-स्तर पर लागू नहीं किया जा सकता है।
- ऐतिहासिक क्वेरी नहीं की जा सकती है, और केवल पंक्ति के नवीनतम संस्करण तक पहुंचा जा सकता है।
- उनके 32-बिट काउंटर प्रकृति के कारण, लेनदेन ID ओवरफ्लो और वैक्यूमिंग के दौरान रीसेट होने के लिए प्रवण होते हैं।
- लेनदेन ID के आधार पर वॉच कार्यक्षमता को लागू करना संभव नहीं है।
परिणामस्वरूप, PostgreSQL को कॉन्फ़िगरेशन डेटा के लिए संस्करण नियंत्रण के लिए वैकल्पिक तरीकों की आवश्यकता होती है क्योंकि अंतर्निहित समर्थन उपलब्ध नहीं है।
क्लाइंट इंटरफेस
क्लाइंट इंटरफेस का डिज़ाइन एक महत्वपूर्ण पहलू है जब इसके उपयोग से जुड़ी लागत और संसाधन खपत को निर्धारित करने की बात आती है। इंटरफेस के बीच के अंतरों का विश्लेषण करके, सबसे उपयुक्त विकल्प चुनते समय सूचित निर्णय लिया जा सकता है।
etcd के kv/watch/lease API कॉन्फ़िगरेशन प्रबंधन में विशेष रूप से कुशल साबित हुए हैं। हालांकि, इन API को PostgreSQL में कैसे लागू किया जा सकता है?
दुर्भाग्य से, PostgreSQL इन API के लिए अंतर्निहित समर्थन प्रदान नहीं करता है, और उन्हें लागू करने के लिए एनकैप्सुलेशन आवश्यक है। उनके कार्यान्वयन का विश्लेषण करने के लिए, हम मेरे द्वारा विकसित pg_watch_demo प्रोजेक्ट की जांच करेंगे: pg_watch_demo.
gRPC/HTTP बनाम TCP
PostgreSQL एक मल्टी-प्रोसेस आर्किटेक्चर का पालन करता है, जहां प्रत्येक प्रोसेस एक समय में केवल एक TCP कनेक्शन को संभालता है। यह SQL क्वेरी के माध्यम से कार्यक्षमता प्रदान करने के लिए एक कस्टम प्रोटोकॉल का उपयोग करता है और एक अनुरोध-प्रतिक्रिया इंटरैक्शन मॉडल का पालन करता है (HTTP/1.1 के समान, जो एक समय में केवल एक अनुरोध को संभालता है और एक साथ कई अनुरोधों को प्रसंस्कृत करने के लिए पाइपलाइनिंग की आवश्यकता होती है)। हालांकि, उच्च संसाधन खपत और अपेक्षाकृत कम दक्षता को देखते हुए, उच्च QPS वाले परिदृश्यों में प्रदर्शन में सुधार के लिए एक कनेक्शन पूल प्रॉक्सी (जैसे pgbouncer) महत्वपूर्ण है।
दूसरी ओर, etcd Golang में एक मल्टी-कोरोटीन आर्किटेक्चर पर डिज़ाइन किया गया है और दो उपयोगकर्ता-अनुकूल इंटरफेस प्रदान करता है: gRPC और RESTful। ये इंटरफेस एकीकृत करने में आसान हैं और संसाधन खपत के मामले में कुशल हैं। इसके अलावा, प्रत्येक gRPC कनेक्शन कई समवर्ती क्वेरी को संभाल सकता है, जो इष्टतम प्रदर्शन सुनिश्चित करता है।
डेटा को परिभाषित करना
etcd
message KeyValue { bytes key = 1; // कुंजी बनाए जाने पर संस्करण संख्या int64 create_revision = 2; // कुंजी अंतिम बार संशोधित होने पर संस्करण संख्या int64 mod_revision = 3; // एक बढ़ता हुआ काउंटर जो हर बार कुंजी अद्यतन होने पर बढ़ता है। // यह काउंटर कुंजी हटाए जाने पर शून्य पर रीसेट हो जाता है, और एक टॉम्बस्टोन के रूप में उपयोग किया जाता है। int64 version = 4; bytes value = 5; // TTL के लिए कुंजी द्वारा उपयोग किया जाने वाला लीज़ ऑब्जेक्ट। यदि मान 0 है, तो कोई TTL नहीं है। int64 lease = 6; }
PostgreSQL
PostgreSQL को etcd के वैश्विक डेटा स्थान का अनुकरण करने के लिए एक टेबल का उपयोग करने की आवश्यकता है:
CREATE TABLE IF NOT EXISTS config ( key text, value text, -- `create_revision` और `mod_revision` के समकक्ष -- यहां, संस्करण का अनुकरण करने के लिए एक बड़ा पूर्णांक बढ़ता हुआ अनुक्रम प्रकार का उपयोग किया जाता है revision bigserial, -- टॉम्बस्टोन tombstone boolean NOT NULL DEFAULT false, -- संयुक्त इंडेक्स, पहले कुंजी से खोजें, फिर संस्करण से primary key(key, revision) );
get
etcd
etcd के get API में विस्तृत पैरामीटर होते हैं:
- रेंज क्वेरी, उदाहरण के लिए,
keyको/abcऔरrange_endको/abdसेट करने से/abcको प्रीफिक्स के रूप में रखने वाले सभी कुंजी-मूल्य जोड़ी प्राप्त होंगी। - ऐतिहासिक क्वेरी,
revisionयाmod_revisionकी एक रेंज निर्दिष्ट करना। - लौटाए गए परिणामों को सॉर्ट करना और सीमित करना।
message RangeRequest { ... bytes key = 1; // रेंज क्वेरी bytes range_end = 2; int64 limit = 3; // ऐतिहासिक क्वेरी int64 revision = 4; // सॉर्टिंग SortOrder sort_order = 5; SortTarget sort_target = 6; bool serializable = 7; bool keys_only = 8; bool count_only = 9; // ऐतिहासिक क्वेरी int64 min_mod_revision = 10; int64 max_mod_revision = 11; int64 min_create_revision = 12; int64 max_create_revision = 13; }
PostgreSQL
PostgreSQL SQL के माध्यम से etcd के get फ़ंक्शन को निष्पादित कर सकता है, और यहां तक कि अधिक जटिल कार्यक्षमता प्रदान कर सकता है। चूंकि SQL स्वयं एक भाषा है न कि एक निश्चित-पैरामीटर इंटरफेस, यह अत्यधिक बहुमुखी है। यहां हम नवीनतम कुंजी-मूल्य जोड़ी को पुनः प्राप्त करने का एक सरल उदाहरण दिखाते हैं। चूंकि प्राथमिक कुंजी एक संयुक्त इंडेक्स है, इसे रेंज द्वारा तेजी से खोजा जा सकता है, जिसके परिणामस्वरूप उच्च-गति वाली पुनः प्राप्ति होती है।
CREATE FUNCTION get1(kk text) RETURNS table(r bigint, k text, v text, c bigint) AS $$ SELECT revision, key, value, create_time FROM config where key = kk and tombstone = false ORDER BY key, revision desc