1 पॉइंट द्वारा GN⁺ 2025-12-09 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • वितरित मैसेजिंग सिस्टम NATS JetStream की durability और consistency की Jepsen ने अलग-अलग fault परिस्थितियों में जाँच की।
  • परीक्षण परिणामों में फाइल करप्शन (.blk, snapshot) और पावर फेल्योर सिमुलेशन के दौरान डेटा लॉस तथा split-brain घटना सामने आई।
  • JetStream डिफ़ॉल्ट रूप से हर 2 मिनट में fsync करता है, जिससे हाल ही में acknowledge हुए संदेश डिस्क पर लिखे बिना रह सकते हैं।
  • केवल एक नोड के OS crash से भी डेटा लॉस और replica mismatch हो सकता है।
  • Jepsen ने NATS में fsync=always को default सेटिंग बदलने या डेटा लॉस के जोखिम को स्पष्ट रूप से दस्तावेज़ित करने की सलाह दी।

1. पृष्ठभूमि

  • NATS एक लोकप्रिय streaming system है जहाँ संदेशों को stream के रूप में publish/subscribe किया जाता है।
    • JetStream में Raft consensus algorithm का उपयोग करके डेटा replicate होता है और कम से कम एक बार (at-least-once) delivery की गारंटी दी जाती है।
  • JetStream दस्तावेज़ों में Linearizable consistency और always-available होने का दावा है, लेकिन CAP theorem के अनुसार दोनों को साथ में हासिल नहीं किया जा सकता।
  • NATS दस्तावेज़ के अनुसार, 3-node stream में 1 server और 5-node stream में 2 servers की failure सहन की जा सकती है।
  • संदेश को सफलतापूर्वक सेव किया गया माना जाता है जब server publish request को acknowledge कर दे।
  • डेटा consistency के लिए quorum यानी बहुमत nodes की जरूरत होती है; 5-node cluster में कम से कम 3 nodes active होने पर ही नया संदेश store हो सकता है।

2. टेस्ट डिजाइन

  • Jepsen ने JNATS 2.24.0 क्लाइंट और Debian 12 LXC containers वाले वातावरण में टेस्ट रन किए।
    • कुछ टेस्ट में Antithesis environment के साथ official NATS Docker image इस्तेमाल की गई।
  • एक single JetStream stream (replication factor 5) सेट करके process stop, crash, network partition, packet loss, file corruption जैसी fault scenarios inject की गईं।
  • LazyFS file system से fsync न होने वाले writes को खो देने वाला power-failure simulation चलाया गया।
  • प्रत्येक process ने unique messages publish किए और टेस्ट खत्म होने पर सभी nodes में acknowledged messages मौजूद हैं या नहीं इसकी verification की गई।
  • यदि message केवल कुछ nodes पर मिले, तो उसे divergence (replication mismatch) के रूप में वर्गीकृत किया गया।

3. मुख्य परिणाम

3.1 NATS 2.10.22 में पूर्ण डेटा लॉस (#6888)

  • सिर्फ process crash से ही पूरे JetStream stream के गायब होने की घटना पाई गई।
  • "No matching streams for subject" error आने के बाद कई घंटों तक recovery नहीं हुआ।
  • कारणों में leader snapshot reversal, Raft state हटाना जैसी स्थिति शामिल थी, और इसे 2.10.23 में fix कर दिया गया।

3.2 .blk फाइल करप्शन पर डेटा लॉस (#7549)

  • JetStream की .blk फाइल में single-bit error या truncation होने पर लाखों में acknowledged writes खो गए।
    • उदाहरण: 1,367,069 में से 679,153 संदेश लॉस।
  • केवल कुछ nodes खराब होने पर भी massive data loss और split-brain हुआ।
    • उदाहरण: nodes n1, n3, n5 पर अधिकतम 78% संदेश खो गए।
  • NATS इस issue की जांच कर रहा है।

3.3 Snapshot file करप्शन पर पूर्ण डेटा deletion (#7556)

  • data/jetstream/$SYS/_js_/ में snapshot फाइल करप्ट होने पर node stream को orphaned मान लेता है और पूरे डेटा को delete कर देता है।
  • केवल कुछ nodes खराब होने पर भी cluster quorum उपलब्ध नहीं रहता और stream permanently unavailable हो सकता है।
  • उदाहरण: nodes n3, n5 खराब → n3 leader चुना गया और jepsen-stream पूरी तरह हट गया।
  • Jepsen ने point out किया कि leader election में damaged node का leader बन जाना बड़ा risk है।

3.4 Default fsync सेटिंग से डेटा लॉस (#7564)

  • JetStream डिफ़ॉल्ट तौर पर सिर्फ हर 2 मिनट में fsync करता है, जबकि संदेश तुरंत acknowledge होते हैं।
    • इसका मतलब हाल ही में acknowledge संदेशों में से कई डिस्क पर लिखे बिना रह जाते हैं।
  • power failure या kernel crash के दौरान कई सेकंड के आसपास के acknowledged संदेश खो सकते हैं।
    • उदाहरण: 930,005 में से 131,418 संदेश लॉस।
  • क्रमिक single-node failures होने पर भी पूरा stream delete हो सकता है।
  • दस्तावेज़ों में इस behavior का लगभग कोई उल्लेख नहीं है।
  • Jepsen ने fsync=always default बदलने या डेटा लॉस के जोखिम की स्पष्ट warning की सिफारिश की।

3.5 Single OS crash से split-brain (#7567)

  • केवल एक node के power loss या kernel crash से भी data loss और replication inconsistency हो सकता है।
  • leader-follower setup में जब कुछ nodes केवल memory में commit होने के बाद ही acknowledge करते हैं और उसके बाद crash हो जाता है, तो
    अधिकांश nodes उस write को खो देते हैं और नया state आगे बढ़ जाता है।
  • परीक्षण में single power loss के बाद persistent split-brain देखा गया।
    • प्रत्येक node पर अलग-अलग range के acknowledged संदेश गायब पाए गए।
  • Jepsen ने Kafka के समान उदाहरण का हवाला देते हुए बताया कि Raft-based systems में भी यही risk मौजूद है

4. चर्चा और निष्कर्ष

  • NATS 2.10.22 का पूर्ण डेटा लॉस मुद्दा 2.10.23 में fix हो गया।
  • NATS 2.12.1 में अभी भी file corruption और OS crash से डेटा लॉस व split-brain संभव हैं।
  • .blk और snapshot file करप्शन की स्थिति में कुछ nodes में संदेश missing हो सकते हैं या पूरा stream हट सकता है।
  • लंबी default fsync interval के कारण कई nodes की simultaneous failure में acknowledged डेटा लॉस का जोखिम बना रहता है।
  • Jepsen ने fsync=always सेट करने या दस्तावेज़ों में clear risk disclosure जोड़ने का सुझाव दिया।
  • JetStream का “always available” दावा CAP theorem के कारण संभव नहीं, इसलिए documentation अपडेट करनी चाहिए।
  • Jepsen ने कहा कि bug मौजूद होने का प्रमाण दिया जा सकता है, पर सुरक्षा का पूर्ण अभाव prove नहीं किया जा सकता

4.1 LazyFS की भूमिका

  • LazyFS से fsync न हुए writes के loss को simulate किया गया।
  • power loss के समय partial write corruption (torn write) जैसे कई storage errors reproduce किए जा सकते हैं।
  • संबंधित शोध When Amnesia Strikes (VLDB 2024) में PostgreSQL, Redis, ZooKeeper आदि में भी similar bugs रिपोर्ट हुए हैं।

4.2 आगे की दिशा

  • single-consumer स्तर पर message loss, message ordering, और Linearizable/Serializable guarantees की verification अभी नहीं की गई।
  • exactly-once delivery guarantee भी आगे के शोध में शामिल होगी।
  • node add/remove करने पर documentation mismatch और ज़रूरी health check step missing पाया गया (#7545)।
  • सुरक्षित cluster reconfiguration प्रक्रिया अभी भी अस्पष्ट है।

1 टिप्पणियां

 
GN⁺ 2025-12-09
Hacker News राय
  • जब भी कोई जटिल सिद्धांत को छोड़कर ऐसा सिस्टम बनाता है, तब aphyr उसे टूटते हुए दिखा देता है
    अब सोच रहा हूँ कि शायद AI प्रोजेक्ट डॉक्यूमेंटेशन पढ़कर सिर्फ मार्केटिंग कॉपी के आधार पर ही डेटा लॉस की संभावना का अनुमान लगा सके
    • लंबी दाढ़ी सहलाते हुए सिर हिलाने जैसा महसूस हो रहा है
      लोग हमेशा कहते हैं कि “सिद्धांत को ज़रूरत से ज़्यादा महत्व दिया गया है” या “स्कूल की पढ़ाई से हैकिंग बेहतर है”, लेकिन आखिर में वे दस्तावेजीकृत problem space में खुद ही फँस जाते हैं
    • मैंने भी LLM से ऐसा ही काम करवाया था, और नतीजा काफ़ी उपयोगी था
  • ऐसा लगता है कि NATS CAP theorem को नज़रअंदाज़ कर रहा है
    • यह बात कम आंकी गई लगती है
  • मैं NATS को in-memory pub/sub के लिए इस्तेमाल करता रहा हूँ, और उस काम में यह शानदार था
    इसने scaling की सूक्ष्म details भी अच्छी तरह संभालीं
    लेकिन मैंने persistence कभी इस्तेमाल नहीं की, और यह इतना नाज़ुक होगा, इसका अंदाज़ा नहीं था
    सिर्फ एक bit की file corruption पर भी इतना संवेदनशील होना चौंकाने वाला है
  • संबंधित सामग्री के तौर पर, Jepsen और Antithesis ने हाल ही में distributed systems glossary जारी की है
    संदर्भ के लिए यह बहुत अच्छी सामग्री है → Jepsen Glossary
  • मैं aphyr.com/tags/jepsen और jepsen.io/analyses के content difference को लेकर उत्सुक था
    हाल ही में aphyr.com मिला, और उससे काफ़ी insights मिलने की उम्मीद है
    • Jepsen मूल रूप से एक personal blog series के रूप में शुरू हुआ था
      बाद में jepsen.io एक professional project के रूप में विकसित हुआ, और लगभग 10 साल पहले से इसे गंभीरता से चलाया जाने लगा
  • यह समझ नहीं आता कि “Lazy fsync by Default” सेटिंग क्यों मौजूद है
    क्या यह benchmark performance बढ़ाने के लिए है? छोटे clusters में ऐसी सेटिंग अक्सर समस्या की जड़ बन जाती है
    • सिर्फ latency ही नहीं, throughput भी बढ़ता है
      कई applications को पूरी durability की ज़रूरत नहीं होती, इसलिए lazy fsync उपयोगी हो सकता है
      लेकिन इसे default रखना विवादास्पद है
    • मैं हमेशा सोचता रहा हूँ कि fsync को ज़रूर delay क्यों करना चाहिए
      TCP corking की तरह batching से भी शायद यह हल हो सकता है
    • यह distributed systems में संभव होने वाली चीज़ों में से एक है
      lazy fsync से होने वाली failures आम तौर पर ज़्यादातर nodes पर एक साथ नहीं होतीं
    • यह performance बढ़ाने के लिए किया गया चुनाव है
    • replication और distribution के ज़रिए durability, और lazy fsync से throughput—दोनों हासिल करने की कोशिश
  • JetStream के serverless alternative के रूप में s2.dev की सिफारिश की गई
    फ़ायदे: object storage-स्तर की durability के साथ unlimited streams का समर्थन
    नुकसान: अभी consumer group फीचर नहीं है
    • जानना चाहूँगा कि क्या इस पर कभी Jepsen test चलाया गया है
  • समस्या यह है कि NATS डिफ़ॉल्ट रूप से हर 2 मिनट में ही fsync करता है, और ack तुरंत लौटा देता है
    अगर कई nodes एक साथ fail हो जाएँ, तो committed data loss हो सकता है
    इससे MongoDB के शुरुआती दौर की “web scale” मार्केटिंग याद आती है
    मेरा मानना है कि default हमेशा सबसे सुरक्षित विकल्प होना चाहिए
    • NATS स्पष्ट रूप से कहता है कि वह सिर्फ cluster availability की गारंटी देता है
      मुझे यही बात अच्छी लगी थी, और उसके ऊपर सिस्टम डिज़ाइन किया जा सकता था
      2018 में जब मैंने इसका इस्तेमाल किया था, तब इसकी performance भी अच्छी थी और इसे manage करना भी आसान था
    • ज़्यादातर modern DBs के defaults भी पूरी तरह safe नहीं होते
      उदाहरण के लिए PostgreSQL का default transaction isolation level read committed है
      Redis भी default रूप से हर 1 सेकंड में fsync करता है
    • Redis cluster कई nodes पर replicate होने के बाद ही ack लौटाता है
      standalone Redis में भी fsync के बाद ack देने की setting संभव है, लेकिन OS buffering की वजह से पूरी गारंटी मुश्किल है
      आख़िरकार ack का मतलब ठीक से समझना ज़रूरी है
    • ज़्यादातर systems speed और durability के बीच समझौता चुनते हैं
      अगर सिर्फ safe defaults पर ही अड़े रहें, तो performance बहुत गिर जाती है और users पर खुद tuning करने का बोझ बढ़ता है
      उदाहरण के लिए Postgres का default isolation level भी इतना कमज़ोर है कि race condition हो सकती है
      संदर्भ: Hermitage test article
    • समस्या यह है कि fsync में सिर्फ चरम विकल्प ही बचे हैं
      SSD के दौर में group-commit जैसे बीच के चरण गायब हो गए, और अब syscall switching cost ही bottleneck है
      2 मिनट का अंतराल बहुत लंबा है (fdatasync vs fsync का फ़र्क भी ध्यान में रखना चाहिए)
  • सच कहूँ तो, कुछ हद तक इसकी उम्मीद थी, लेकिन यह इतना गंभीर होगा, यह नहीं सोचा था
    शायद बस Redpanda इस्तेमाल करना बेहतर होगा
  • मैं सोच रहा था कि क्या NATS की fsync performance warning को बेहतर बनाया जा सकता है
    अगर तय अंतराल पर batch flush किया जाए, तो latency बढ़ेगी लेकिन throughput शायद बरकरार रह सके
    • किसी fixed interval के बजाय, जब fsync चल रहा हो तब write requests को queue करके अगली batch में साथ प्रोसेस किया जा सकता है
      यह Paxos rounds को एक साथ बाँधने जैसा है
      एक round खत्म होते ही अगली batch तुरंत शुरू कर देनी चाहिए