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

आदि राफ्ट लाइब्रेरी का उपयोग करके अपना खुद का वितरित केवी स्टोरेज सिस्टम कैसे बनाएं

2024-07-30 को प्रकाशित
ब्राउज़ करें:597

How to Build Your Own Distributed KV Storage System Using the etcd Raft Library

परिचय

raftexample, आदि द्वारा प्रदान किया गया एक उदाहरण है जो आदि राफ्ट सर्वसम्मति एल्गोरिदम लाइब्रेरी के उपयोग को प्रदर्शित करता है। राफ़्टेक्सैम्पल अंततः एक वितरित कुंजी-मूल्य भंडारण सेवा लागू करता है जो एक REST API प्रदान करता है।

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

वास्तुकला

Raftexample का आर्किटेक्चर बहुत सरल है, मुख्य फ़ाइलें इस प्रकार हैं:

  • main.go: राफ्ट मॉड्यूल, httpapi मॉड्यूल और kvstore मॉड्यूल के बीच बातचीत को व्यवस्थित करने के लिए जिम्मेदार;
  • raft.go: राफ्ट लाइब्रेरी के साथ बातचीत करने के लिए जिम्मेदार, जिसमें प्रस्ताव प्रस्तुत करना, भेजे जाने वाले आरपीसी संदेश प्राप्त करना और नेटवर्क ट्रांसमिशन करना आदि शामिल है;
  • httpapi.go: उपयोगकर्ता अनुरोधों के लिए प्रवेश बिंदु के रूप में सेवा करते हुए, REST एपीआई प्रदान करने के लिए जिम्मेदार;
  • kvstore.go: राफ्ट प्रोटोकॉल में राज्य मशीन के बराबर प्रतिबद्ध लॉग प्रविष्टियों को लगातार संग्रहीत करने के लिए जिम्मेदार।

एक लिखित अनुरोध का प्रसंस्करण प्रवाह

HTTP PUT अनुरोध के माध्यम से httpapi मॉड्यूल की ServeHTTP विधि में एक लेखन अनुरोध आता है।

curl -L http://127.0.0.1:12380/key -XPUT -d value

स्विच के माध्यम से HTTP अनुरोध विधि से मिलान करने के बाद, यह PUT विधि प्रसंस्करण प्रवाह में प्रवेश करता है:

  • HTTP अनुरोध निकाय से सामग्री पढ़ें (यानी, मूल्य);
  • केवीस्टोर मॉड्यूल की प्रस्ताव विधि के माध्यम से एक प्रस्ताव का निर्माण करें (कुंजी के रूप में कुंजी और मूल्य के रूप में मूल्य के साथ एक कुंजी-मूल्य जोड़ी जोड़ना);
  • चूंकि वापस करने के लिए कोई डेटा नहीं है, इसलिए 204 स्टेटसनोकंटेंट के साथ क्लाइंट को जवाब दें;

प्रस्ताव राफ्ट एल्गोरिथम लाइब्रेरी द्वारा प्रदान की गई प्रस्ताव विधि के माध्यम से राफ्ट एल्गोरिथम लाइब्रेरी को प्रस्तुत किया गया है।

प्रस्ताव की सामग्री में एक नई कुंजी-मूल्य जोड़ी जोड़ना, मौजूदा कुंजी-मूल्य जोड़ी को अपडेट करना आदि शामिल हो सकता है।

// httpapi.go
v, err := io.ReadAll(r.Body)
if err != nil {
    log.Printf("Failed to read on PUT (%v)\n", err)
    http.Error(w, "Failed on PUT", http.StatusBadRequest)
    return
}
h.store.Propose(key, string(v))
w.WriteHeader(http.StatusNoContent)

इसके बाद, आइए kvstore मॉड्यूल की प्रपोज विधि पर नजर डालें कि प्रस्ताव कैसे बनाया और संसाधित किया जाता है।

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

// kvstore.go
func (s *kvstore) Propose(k string, v string) {
    var buf strings.Builder
    if err := gob.NewEncoder(&buf).Encode(kv{k, v}); err != nil {
        log.Fatal(err)
    }
    s.proposeC 



केवीस्टोर द्वारा निर्मित और प्रपोजसी को पारित प्रस्ताव राफ्ट मॉड्यूल में सर्वचैनल्स विधि द्वारा प्राप्त और संसाधित किया जाता है।

यह पुष्टि करने के बाद कि प्रपोजसी को बंद नहीं किया गया है, राफ्ट मॉड्यूल राफ्ट एल्गोरिदम लाइब्रेरी द्वारा प्रदान की गई प्रपोज विधि का उपयोग करके प्रसंस्करण के लिए प्रस्ताव को राफ्ट एल्गोरिदम लाइब्रेरी में जमा करता है।

// raft.go
select {
    case prop, ok := 



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

हालाँकि, चूंकि आदि राफ्ट लाइब्रेरी स्वयं नोड्स के बीच संचार, राफ्ट लॉग को जोड़ना, राज्य मशीन पर लागू करना आदि को संभाल नहीं पाती है, इसलिए राफ्ट लाइब्रेरी केवल इन परिचालनों के लिए आवश्यक डेटा तैयार करती है। वास्तविक संचालन हमारे द्वारा किया जाना चाहिए।

इसलिए, हमें इस डेटा को राफ्ट लाइब्रेरी से प्राप्त करने और इसके प्रकार के आधार पर इसे संसाधित करने की आवश्यकता है। रेडी विधि एक रीड-ओनली चैनल लौटाती है जिसके माध्यम से हम वह डेटा प्राप्त कर सकते हैं जिसे संसाधित करने की आवश्यकता है।

यह ध्यान दिया जाना चाहिए कि प्राप्त डेटा में कई फ़ील्ड शामिल हैं, जैसे लागू किए जाने वाले स्नैपशॉट, राफ्ट लॉग में जोड़े जाने वाली लॉग प्रविष्टियां, नेटवर्क पर प्रसारित होने वाले संदेश, आदि।

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

चूंकि हम वर्तमान में लीडर नोड हैं, राफ्ट लाइब्रेरी हमें MsgApp प्रकार के संदेश लौटाएगी (पेपर में AppendEntries RPC के अनुरूप)। हमें इन संदेशों को अनुयायी नोड्स को भेजने की आवश्यकता है। यहां, हम नोड संचार के लिए आदि द्वारा प्रदान किए गए राफ्टhttp का उपयोग करते हैं और सेंड विधि का उपयोग करके अनुयायियों को संदेश भेजते हैं।

// raft.go
case rd := 



इसके बाद, हम राज्य मशीन पर प्रतिबद्ध राफ्ट लॉग प्रविष्टियों को लागू करने के लिए पब्लिशएंट्रीज़ विधि का उपयोग करते हैं। जैसा कि पहले उल्लेख किया गया है, राफ्टएक्सैम्पल में, केवीस्टोर मॉड्यूल राज्य मशीन के रूप में कार्य करता है। पब्लिशएंट्रीज़ विधि में, हम उन लॉग प्रविष्टियों को पास करते हैं जिन्हें कमिटसी के लिए राज्य मशीन पर लागू करने की आवश्यकता होती है। पहले के प्रस्तावसी के समान, कमिटसी उन लॉग प्रविष्टियों को प्रसारित करने के लिए जिम्मेदार है जिन्हें राफ्ट मॉड्यूल ने राज्य मशीन पर आवेदन के लिए केवीस्टोर मॉड्यूल के लिए प्रतिबद्ध माना है।

// raft.go
rc.commitC 



केवीस्टोर मॉड्यूल की रीडकमिट्स विधि में, कमिटसी से पढ़े गए संदेशों को मूल कुंजी-मूल्य जोड़े को पुनः प्राप्त करने के लिए गोब-डिकोड किया जाता है, जिन्हें फिर केवीस्टोर मॉड्यूल के भीतर एक मानचित्र संरचना में संग्रहीत किया जाता है।

// kvstore.go
for commit := range commitC {
    ...
    for _, data := range commit.data {
        var dataKv kv
        dec := gob.NewDecoder(bytes.NewBufferString(data))
        if err := dec.Decode(&dataKv); err != nil {
            log.Fatalf("raftexample: could not decode message (%v)", err)
        }
        s.mu.Lock()
        s.kvStore[dataKv.Key] = dataKv.Val
        s.mu.Unlock()
    }
    close(commit.applyDoneC)
}

राफ्ट मॉड्यूल पर लौटते हुए, हम राफ्ट लाइब्रेरी को सूचित करने के लिए एडवांस विधि का उपयोग करते हैं कि हमने रेडी चैनल से पढ़े गए डेटा को संसाधित करना समाप्त कर लिया है और डेटा के अगले बैच को संसाधित करने के लिए तैयार हैं।

इससे पहले, लीडर नोड पर, हमने सेंड विधि का उपयोग करके फॉलोअर नोड्स को MsgApp प्रकार के संदेश भेजे थे। फॉलोअर नोड का राफ्टhttp अनुरोध प्राप्त करने और प्रतिक्रियाएँ वापस करने के लिए संबंधित पोर्ट पर सुनता है। चाहे यह अनुयायी नोड द्वारा प्राप्त अनुरोध हो या लीडर नोड द्वारा प्राप्त प्रतिक्रिया हो, इसे चरण विधि के माध्यम से प्रसंस्करण के लिए राफ्ट लाइब्रेरी में प्रस्तुत किया जाएगा।

raftNode, Rafthttp में Raft इंटरफ़ेस को कार्यान्वित करता है, और Raft इंटरफ़ेस की प्रक्रिया विधि को प्राप्त अनुरोध सामग्री (जैसे MsgApp संदेश) को संभालने के लिए कहा जाता है।

// raft.go
func (rc *raftNode) Process(ctx context.Context, m raftpb.Message) error {
    return rc.node.Step(ctx, m)
}

उपरोक्त राफ्ट उदाहरण में एक लेखन अनुरोध के संपूर्ण प्रसंस्करण प्रवाह का वर्णन करता है।

सारांश

यह इस लेख की सामग्री को समाप्त करता है। राफ्टएक्सैम्पल की संरचना की रूपरेखा और एक लेखन अनुरोध के प्रसंस्करण प्रवाह का विवरण देकर, मुझे आशा है कि मैं आपको बेहतर ढंग से समझने में मदद करूंगा कि अपनी स्वयं की वितरित केवी भंडारण सेवा बनाने के लिए आदि राफ्ट लाइब्रेरी का उपयोग कैसे करें।

यदि कोई गलती या समस्या है, तो कृपया बेझिझक टिप्पणी करें या मुझे सीधे संदेश भेजें। धन्यवाद।

संदर्भ

  • https://github.com/etcd-io/etcd/tree/main/contrib/raftexample

  • https://github.com/etcd-io/raft

  • https://raft.github.io/raft.pdf

विज्ञप्ति वक्तव्य यह आलेख यहां पुन: प्रस्तुत किया गया है: https://dev.to/justlorain/how-to-build-your-own-distributed-kv-storage-system-using-the-etcd-raft-library-2j69?1यदि कोई है उल्लंघन, हटाने के लिए कृपया [email protected] से संपर्क करें
नवीनतम ट्यूटोरियल अधिक>

चीनी भाषा का अध्ययन करें

अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।

Copyright© 2022 湘ICP备2022001581号-3