Node.js बैकएंड विकास बूटकैंप · पाठ

वितरित लॉक और Redlock एल्गोरिदम

इंस्टैंसों के बीच अनन्य पहुँच का सुरक्षित समन्वय कीजिए और वितरित लॉकिंग की सीमाएँ समझिए।

पाठ 2, कुल 4 में से13 चरण

वितरित लॉक और Redlock एल्गोरिदम, CoddyKit पर Node.js बैकएंड विकास बूटकैंप का एक निःशुल्क पाठ है। यह 4 में से 2वाँ पाठ है। आप नीचे पूरा पाठ निःशुल्क पढ़ सकते हैं—फिर अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर के साथ ब्राउज़र में इसका व्यावहारिक अभ्यास कर सकते हैं। यह Node.js बैकएंड विकास बूटकैंप सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। Node.js बैकएंड विकास बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

वितरित लॉक क्यों?

जब आपका Node.js API एकल प्रक्रिया के रूप में चलता है, तो किसी महत्वपूर्ण खंड तक पहुँच को क्रमबद्ध करने के लिए साधारण इन-मेमोरी म्यूटेक्स पर्याप्त होता है। लेकिन उत्पादन बैकएंड लोड बैलेंसर के पीछे, अक्सर कई मशीनों पर, कई इंस्टेंस चलाते हैं।

  • दो पॉड एक ही चालान का शुल्क लेने का प्रयास कर सकते हैं।
  • दो कार्यकर्ता कतार से एक ही कार्य उठा सकते हैं।
  • दो अनुरोध एक ही महँगी कैश प्रविष्टि को फिर से बना सकते हैं (कैश स्टैम्पीड)।

इन-मेमोरी लॉक केवल एक प्रक्रिया के भीतर रहता है — अन्य इंस्टेंस को उसके बारे में कुछ पता नहीं होता। इंस्टेंसों के बीच विशेष पहुँच का समन्वय करने के लिए आपको ऐसे लॉक की आवश्यकता होती है जो साझा बाहरी संग्रहण में रहता हो, और Redis इसके लिए लोकप्रिय विकल्प है।

पहला (सरल) Redis लॉक

मूल आदिम क्रिया परमाणु SET key value NX PX ttl कमांड है। NX का अर्थ है "केवल तभी सेट करें जब कुंजी मौजूद न हो", और PX मिलीसेकंड में समाप्ति निर्धारित करता है, ताकि लॉक रखने वाली प्रक्रिया के क्रैश होने पर लॉक अपने-आप रिलीज़ हो जाए।

  • यदि SET OK लौटाता है, तो आपने लॉक प्राप्त कर लिया है।
  • यदि यह null लौटाता है, तो लॉक किसी और के पास है।

प्रत्येक बार लॉक प्राप्त करते समय मान एक अद्वितीय यादृच्छिक टोकन होना चाहिए — सुरक्षित रूप से रिलीज़ करने के लिए बाद में इसकी आवश्यकता होगी।

const { createClient } = require('redis');
const crypto = require('crypto');

async function acquire(redis, key, ttlMs) {
  const token = crypto.randomUUID();
  // NX = set only if absent, PX = expiry in ms
  const ok = await redis.set(key, token, { NX: true, PX: ttlMs });
  return ok === 'OK' ? token : null;
}

// Usage sketch (needs a running Redis):
// const redis = createClient(); await redis.connect();
// const token = await acquire(redis, 'lock:invoice:42', 10000);
// if (token) { /* do exclusive work */ }

सुरक्षित रिलीज़: जाँच-और-हटाना

रिलीज़ करना सबसे जोखिमपूर्ण भाग है। एक सरल DEL key किसी और का लॉक हटा सकता है: यदि आपका काम TTL से अधिक समय तक चला, तो लॉक समाप्त हो गया, किसी अन्य इंस्टेंस ने उसे प्राप्त कर लिया और फिर आपका देर से किया गया DEL उसका लॉक मिटा देता है।

समाधान: केवल तभी हटाएँ जब संग्रहीत मान अभी भी आपके टोकन के बराबर हो। जाँच-फिर-हटाना परमाणु होना चाहिए, इसलिए इसे Lua स्क्रिप्ट के रूप में चलाएँ — Redis अन्य कमांड के बीच में हस्तक्षेप किए बिना स्क्रिप्ट चलाता है।

const RELEASE_LUA = `
if redis.call('get', KEYS[1]) == ARGV[1] then
  return redis.call('del', KEYS[1])
else
  return 0
end`;

async function release(redis, key, token) {
  // Returns 1 if we owned and removed it, 0 otherwise
  return redis.eval(RELEASE_LUA, { keys: [key], arguments: [token] });
}

TTL: सबसे कठिन समायोजन निर्णय

TTL इस बात का अनुमान है कि आपके महत्वपूर्ण खंड को पूरा होने में कितना समय लगता है।

  • बहुत कम होने पर लॉक काम के बीच में समाप्त हो जाता है और दूसरा कार्यकर्ता अंदर आ सकता है — आपका पारस्परिक बहिष्करण टूट जाता है।
  • बहुत अधिक होने पर, लॉक रखने वाली प्रक्रिया के क्रैश होने पर किसी के आगे बढ़ने से पहले सभी को पूरी TTL अवधि तक प्रतीक्षा करनी पड़ती है।

सामान्य नियम: TTL को महत्वपूर्ण खंड की p99 अवधि के कुछ गुना के बराबर रखें, सुरक्षित किए गए काम को छोटा रखें, और लंबे कार्यों के लिए एक बहुत बड़ी TTL के बजाय ऐसा वॉचडॉग उपयोग करें जो समय-समय पर लॉक की अवधि बढ़ाता रहे।

लॉक की अवधि बढ़ाना (वॉचडॉग पैटर्न)

जिस काम की अवधि निश्चित न हो, उसके लिए मध्यम TTL प्राप्त करें और जब तक लॉक आपके पास हो, टाइमर के माध्यम से उसे नवीनीकृत करते रहें। रिलीज़ की तरह, अवधि बढ़ाने की प्रक्रिया भी आपके टोकन से सुरक्षित होनी चाहिए, ताकि जो लॉक किसी और को मिल चुका हो उसकी अवधि आप कभी न बढ़ाएँ।

वॉचडॉग लगभग TTL के एक-तिहाई समय पर चलता है, जिससे घड़ी के उतार-चढ़ाव और GC रुकावटों के लिए अतिरिक्त गुंजाइश मिलती है।

const EXTEND_LUA = `
if redis.call('get', KEYS[1]) == ARGV[1] then
  return redis.call('pexpire', KEYS[1], ARGV[2])
else
  return 0
end`;

function startWatchdog(redis, key, token, ttlMs) {
  const timer = setInterval(async () => {
    const ok = await redis.eval(EXTEND_LUA, {
      keys: [key], arguments: [token, String(ttlMs)],
    });
    if (ok !== 1) clearInterval(timer); // lost the lock; stop renewing
  }, Math.floor(ttlMs / 3));
  return () => clearInterval(timer);
}

एकल-नोड Redis एक SPOF है

अब तक की पूरी चर्चा एक Redis नोड मानकर की गई है। वह नोड विफलता का एकल बिंदु है, इसलिए टीमें फ़ेलओवर के साथ एक प्रतिकृति जोड़ती हैं। लेकिन Redis प्रतिकृति अतुल्यकालिक होती है, और इससे चुपचाप पारस्परिक बहिष्करण टूट जाता है:

  • Client A मास्टर पर लॉक प्राप्त करता है।
  • मास्टर, लेखन को प्रतिकृति में दोहराने से पहले क्रैश हो जाता है।
  • प्रतिकृति को मास्टर बना दिया जाता है; उसके पास लॉक का कोई रिकॉर्ड नहीं होता।
  • Client B नए मास्टर पर "वही" लॉक प्राप्त कर लेता है।

अब दो Client एक ही समय पर लॉक धारण कर रहे हैं। Redlock एल्गोरिदम इसी फ़ेलओवर अवधि की समस्या को दूर करने के लिए बनाया गया था।

Redlock एल्गोरिदम

Redlock N स्वतंत्र Redis मास्टर का उपयोग करता है (आमतौर पर 5), और इनके बीच कोई प्रतिकृति नहीं होती। लॉक प्राप्त करने के लिए Client:

  • आरंभ समय दर्ज करता है, फिर हर नोड पर छोटे, प्रति-नोड timeout के साथ सभी N नोड में एक ही key+token पर SET NX PX आज़माता है।
  • सफलताओं की गिनती करता है। लॉक तभी प्राप्त माना जाता है जब quorum (N/2 + 1, अर्थात 5 में से 3) मिल जाए और कुल बीता हुआ समय TTL से कम हो।
  • प्रभावी वैधता = TTL में से बीता हुआ समय और clock-drift allowance घटाने पर प्राप्त मान।

यदि quorum नहीं मिल पाता (या समय समाप्त हो जाता) है, तो वह सभी नोड से लॉक हटाता है और थोड़ी यादृच्छिक देरी के बाद फिर प्रयास करता है।

redlock लाइब्रेरी का उपयोग

आप Redlock को हाथ से बहुत कम ही लागू करते हैं। redlock npm पैकेज स्वतंत्र Redis Client की एक array लेता है और using() उपलब्ध कराता है, जो आपके callback के आसपास लॉक प्राप्त, स्वतः विस्तारित और जारी करता है।

  • retryCount / retryDelay यह नियंत्रित करते हैं कि हार मानने से पहले यह कितनी बार और कितनी देर तक प्रयास करे।
  • using() आपको एक signal देता है — काम के बीच लॉक खो जाने का पता लगाने के लिए signal.aborted जाँचें।
const Client = require('ioredis');
const Redlock = require('redlock').default;

const nodes = [
  new Client({ host: 'redis-a' }),
  new Client({ host: 'redis-b' }),
  new Client({ host: 'redis-c' }),
];

const redlock = new Redlock(nodes, {
  retryCount: 10,
  retryDelay: 200,   // ms between attempts
  driftFactor: 0.01, // clock-drift allowance
});

async function chargeInvoice(id) {
  await redlock.using([`lock:invoice:${id}`], 5000, async (signal) => {
    await doCharge(id);
    if (signal.aborted) throw signal.error; // lost the lock
  });
}

फेंसिंग टोकन: वास्तविक सुरक्षा-जाल

Martin Kleppmann की प्रसिद्ध आलोचना यह है: यदि कोई लॉक-धारक (GC या VM stall के कारण) TTL समाप्त होने तक रुका रहे, तो समय-सीमा पर आधारित कोई भी लॉक सुरक्षा की गारंटी नहीं दे सकता। लॉक समाप्त हो जाता है, दूसरा Client आगे बढ़ जाता है, और रुका हुआ Client जागने पर अब भी मानता है कि लॉक उसके पास है।

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

// Resource-side guard: reject writes with a stale fencing token.
function makeFencedStore() {
  let highestSeen = 0;
  const data = {};
  return {
    write(key, value, token) {
      if (token <= highestSeen) {
        throw new Error(`fenced: token ${token} <= ${highestSeen}`);
      }
      highestSeen = token;
      data[key] = value;
      return token;
    },
  };
}

const store = makeFencedStore();
store.write('balance', 100, 33);     // ok, token 33
try {
  store.write('balance', 999, 32);   // stale writer, fenced out
} catch (e) {
  console.log(e.message);            // fenced: token 32 <= 33
}
console.log('stored:', store.write('balance', 200, 34)); // 34

लॉक बनाम idempotency

लॉक समवर्ती निष्पादन की संभावना कम करता है, लेकिन timeout और फ़ेलओवर के कारण इसे कभी पूर्ण गारंटी नहीं बनाया जा सकता। लॉक को अनुकूलन मानें, अंतिम सुरक्षा-पंक्ति नहीं।

  • सुरक्षित किए गए ऑपरेशन को idempotent बनाएँ — उसे दो बार चलाने पर भी वही परिणाम मिले।
  • डेटाबेस की unique constraints या सशर्त अपडेट (compare-and-set) का उपयोग करें, ताकि दोहराया गया लेखन स्पष्ट रूप से विफल हो।
  • जहाँ संसाधन उनका समर्थन करता हो, वहाँ fencing tokens का उपयोग करें।

सर्वोत्तम अभ्यास: व्यर्थ काम और प्रतिस्पर्धा से बचने के लिए लॉक लगाएँ, लेकिन सिस्टम को इस तरह डिज़ाइन करें कि दुर्लभ दोहरा निष्पादन भी सही रहे।

क्या आपको वास्तव में Redlock की आवश्यकता है?

Redlock की परिचालन लागत है: पाँच स्वतंत्र Redis परिनियोजन, सावधानीपूर्वक clock प्रबंधन और retry tuning। redis के अनुरक्षक स्वयं कहते हैं कि दक्षता वाले उपयोग-मामलों (एक ही काम को दो बार करने से बचने) के लिए एकल-नोड लॉक पर्याप्त है — कभी-कभार दोबारा चलने पर बस थोड़ा काम व्यर्थ होता है।

  • दक्षता वाला लॉक (कैश पुनर्निर्माण, डुप्लिकेट हटाना): एकल Redis SET NX PX पर्याप्त है।
  • शुद्धता वाला लॉक (धन, इन्वेंटरी): अकेले किसी भी timeout लॉक पर निर्भर न रहें — Redlock हो या न हो, idempotency और fencing जोड़ें।

Redlock का उपयोग तभी करें जब एकल-नोड HA फ़ेलओवर वास्तव में अस्वीकार्य हो और आप संसाधन पर fencing न कर सकें।

त्वरित जाँच

वितरित लॉकिंग की सुरक्षा की अपनी समझ जाँचें।

पुनरावलोकन

आपने सीखा कि Node.js instances के बीच विशिष्ट पहुँच का समन्वय कैसे करें — और इसकी सीमाएँ कहाँ हैं।

  • प्राप्ति atomic SET key token NX PX ttl से करें; हर प्राप्ति के लिए token अद्वितीय होना चाहिए।
  • जारी करना और विस्तार करना केवल token-जाँच वाली Lua script के माध्यम से करें, ताकि आप कभी किसी और के लॉक को न छुएँ; लंबे कार्यों के लिए watchdog से नवीनीकरण करें।
  • TTL एक संतुलन है: बहुत छोटा होने पर बहिष्करण टूटता है, बहुत लंबा होने पर क्रैश के बाद पुनर्प्राप्ति में देरी होती है।
  • Redlock एकल-नोड फ़ेलओवर से बचने के लिए N स्वतंत्र मास्टर के बीच quorum का उपयोग करता है, लेकिन यह अब भी timeout पर आधारित है।
  • लंबे समय तक रुकने की स्थिति में कोई timeout लॉक सुरक्षित नहीं है — शुद्धता-आधारित महत्वपूर्ण कार्यों के लिए fencing tokens और idempotency जोड़ें।
  • दक्षता के लिए एकल-नोड लॉक उपयोग करें; Redlock को वास्तविक HA आवश्यकताओं के लिए बचाकर रखें।
शुरुआत निःशुल्क

एआई शिक्षक के साथ JavaScript सीखें — निःशुल्क

अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।

पाठ्यक्रम
22
पाठ
92

अक्सर पूछे जाने वाले प्रश्न

क्या “वितरित लॉक और Redlock एल्गोरिदम” पाठ निःशुल्क है?

हाँ—“वितरित लॉक और Redlock एल्गोरिदम” का पूरा पाठ यहाँ वेब पर निःशुल्क पढ़ा जा सकता है। इंटरैक्टिव अभ्यास (अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर) करने और Node.js बैकएंड विकास बूटकैंप पाठ्यक्रम का बाकी हिस्सा अनलॉक करने के लिए CoddyKit PRO लें। Node.js बैकएंड विकास बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“वितरित लॉक और Redlock एल्गोरिदम” में मैं क्या सीखूँगा?

इंस्टैंसों के बीच अनन्य पहुँच का सुरक्षित समन्वय कीजिए और वितरित लॉकिंग की सीमाएँ समझिए। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ Node.js बैकएंड विकास बूटकैंप का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या Node.js बैकएंड विकास बूटकैंप शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर Node.js बैकएंड विकास बूटकैंप शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 2वाँ पाठ है।

“वितरित लॉक और Redlock एल्गोरिदम” पाठ पूरा करने में कितना समय लगता है?

CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।

क्या मैं इस Node.js बैकएंड विकास बूटकैंप पाठ में कोड लिख और चला सकता हूँ?

हाँ। हर Node.js बैकएंड विकास बूटकैंप पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।

इस पाठ्यक्रम के सभी पाठ

  1. कैश-आसाइड, राइट-थ्रू और TTL रणनीतियाँ
  2. वितरित लॉक और Redlock एल्गोरिदम
  3. Redis से Pub/Sub, स्ट्रीम और दर सीमांकन
  4. कैश स्टैम्पीड और थंडरिंग हर्ड रोकना
← Node.js बैकएंड विकास बूटकैंप पर वापस जाएँ