Jepsen: NATS 2.12.1
(jepsen.io)- वितरित मैसेजिंग सिस्टम 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
publishrequest को 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% संदेश खो गए।
- उदाहरण: nodes
- 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खराब →n3leader चुना गया और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=alwaysdefault बदलने या डेटा लॉस के जोखिम की स्पष्ट 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
fsyncinterval के कारण कई 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 टिप्पणियां
Hacker News राय
अब सोच रहा हूँ कि शायद AI प्रोजेक्ट डॉक्यूमेंटेशन पढ़कर सिर्फ मार्केटिंग कॉपी के आधार पर ही डेटा लॉस की संभावना का अनुमान लगा सके
लोग हमेशा कहते हैं कि “सिद्धांत को ज़रूरत से ज़्यादा महत्व दिया गया है” या “स्कूल की पढ़ाई से हैकिंग बेहतर है”, लेकिन आखिर में वे दस्तावेजीकृत problem space में खुद ही फँस जाते हैं
इसने scaling की सूक्ष्म details भी अच्छी तरह संभालीं
लेकिन मैंने persistence कभी इस्तेमाल नहीं की, और यह इतना नाज़ुक होगा, इसका अंदाज़ा नहीं था
सिर्फ एक bit की file corruption पर भी इतना संवेदनशील होना चौंकाने वाला है
संदर्भ के लिए यह बहुत अच्छी सामग्री है → Jepsen Glossary
हाल ही में aphyr.com मिला, और उससे काफ़ी insights मिलने की उम्मीद है
बाद में jepsen.io एक professional project के रूप में विकसित हुआ, और लगभग 10 साल पहले से इसे गंभीरता से चलाया जाने लगा
क्या यह benchmark performance बढ़ाने के लिए है? छोटे clusters में ऐसी सेटिंग अक्सर समस्या की जड़ बन जाती है
कई applications को पूरी durability की ज़रूरत नहीं होती, इसलिए lazy fsync उपयोगी हो सकता है
लेकिन इसे default रखना विवादास्पद है
TCP corking की तरह batching से भी शायद यह हल हो सकता है
lazy fsync से होने वाली failures आम तौर पर ज़्यादातर nodes पर एक साथ नहीं होतीं
फ़ायदे: object storage-स्तर की durability के साथ unlimited streams का समर्थन
नुकसान: अभी consumer group फीचर नहीं है
अगर कई nodes एक साथ fail हो जाएँ, तो committed data loss हो सकता है
इससे MongoDB के शुरुआती दौर की “web scale” मार्केटिंग याद आती है
मेरा मानना है कि default हमेशा सबसे सुरक्षित विकल्प होना चाहिए
मुझे यही बात अच्छी लगी थी, और उसके ऊपर सिस्टम डिज़ाइन किया जा सकता था
2018 में जब मैंने इसका इस्तेमाल किया था, तब इसकी performance भी अच्छी थी और इसे manage करना भी आसान था
उदाहरण के लिए PostgreSQL का default transaction isolation level read committed है
Redis भी default रूप से हर 1 सेकंड में fsync करता है
standalone Redis में भी fsync के बाद ack देने की setting संभव है, लेकिन OS buffering की वजह से पूरी गारंटी मुश्किल है
आख़िरकार ack का मतलब ठीक से समझना ज़रूरी है
अगर सिर्फ safe defaults पर ही अड़े रहें, तो performance बहुत गिर जाती है और users पर खुद tuning करने का बोझ बढ़ता है
उदाहरण के लिए Postgres का default isolation level भी इतना कमज़ोर है कि race condition हो सकती है
संदर्भ: Hermitage test article
SSD के दौर में group-commit जैसे बीच के चरण गायब हो गए, और अब syscall switching cost ही bottleneck है
2 मिनट का अंतराल बहुत लंबा है (fdatasync vs fsync का फ़र्क भी ध्यान में रखना चाहिए)
शायद बस Redpanda इस्तेमाल करना बेहतर होगा
अगर तय अंतराल पर batch flush किया जाए, तो latency बढ़ेगी लेकिन throughput शायद बरकरार रह सके
यह Paxos rounds को एक साथ बाँधने जैसा है
एक round खत्म होते ही अगली batch तुरंत शुरू कर देनी चाहिए