बिल्कुल एक बार बनाम कम से कम एक बार
1) शब्दार्थ पर भी चर्चा क्यों करें
वितरण शब्दार्थ यह निर्धारित करते हैं कि दुर्घटनाग्रस्त होने और पीछे हटने पर प्राप्तकर्ता संदेश कितनी बार देखेगा:- सबसे अधिक बार - पुनरावृत्ति के बिना, लेकिन नुकसान संभव है (शायद ही कभी स्वीकार्य)।
- कम से कम-एक बार - हारना नहीं है, लेकिन डुप्लिकेट संभव है (अधिकांश दलालों/कतारों का डिफ़ॉल्ट)।
- बिल्कुल एक बार - प्रत्येक संदेश को मनाया प्रभाव के संदर्भ में ठीक एक बार संसाधित किया जा
प्रमुख सच्चाई: वैश्विक लेनदेन और तुल्यकालिक स्थिरता के बिना एक वितरित दुनिया में, एक "स्वच्छ" एंड-टू-एंड बिल्कुल एक बार अप्राप्य है। हम प्रभावी रूप से एक बार का निर्माण करते हैं: हम परिवहन पर पुनरावृत्ति की अनुमति देते हैं, लेकिन हम प्रसंस्करण को मूर्त रूप देते हैं ताकि मनाया प्रभाव "जैसे एक बार" हो।
2) विफलता पैटर्न और जहां डुप्लिकेट होते हैं
रिप्ले इसके कारण दिखाई देते हैं:- नुकसान ack/कमिट (निर्माता/ब्रोकर/उपभोक्ता "ने" पुष्टि "नहीं सुनी)।
- नेताओं/प्रतिकृतियों का पुन: चुनाव, नेटवर्क टूटने के बाद वसूली।
- किसी भी क्षेत्र (kliyent→broker→konsyumer→sink) में टाइमआउट/रिट्रीट।
परिणाम: आप परिवहन की "विशिष्टता की विशिष्टता" पर भरोसा नहीं कर सकते। प्रभाव प्रबंधित करें: डेटाबेस में लिखना, पैसे को डेबिट करना, पत्र भेजना आदि।
3) वास्तव में एक बार प्रदाताओं में और यह वास्तव में क्या है
3. 1 काफ्का
ईंटें देता है:- पहचान निर्माता ('सक्षम। पहचान = सही ') - पीछे हटने पर निर्माता की तरफ से डुप्लिकेट को रोकता है।
- लेनदेन - परमाणु रूप से कई बैचों में संदेश प्रकाशित करते हैं और खपत ऑफसेट ("अंतराल" के बिना पढ़ ने-प्रक्रिया-लेखन पैटर्न) करते हैं।
- संपीड़न - कुंजी द्वारा अंतिम मान भंडारित करता है।
लेकिन "श्रृंखला का अंत" (सिंक: डीबी/भुगतान/मेल) को अभी भी पहचान की आवश्यकता है। अन्यथा, हैंडलर का दोहरा प्रभाव दोगुना हो जाएगा।
3. 2 NATS/खरगोश/SQS
डिफ़ॉल्ट ack/redelivery के साथ कम से कम एक बार है। वास्तव में एक बार आवेदन स्तर पर प्राप्त किया जाता है: कुंजी, डेडस्टोर, अपसर्ट।
निष्कर्ष: वास्तव में एक बार परिवहन - बिल्कुल एक बार प्रभाव। उत्तरार्द्ध हैंडलर में किया जाता है।
4) कम से कम एक बार प्रभावी ढंग से कैसे निर्माण करें
4. 1 पहचान कुंजी
प्रत्येक कमांड/इवेंट में एक प्राकृतिक कुंजी होती है: 'पेमेंट _ आईडी', 'ऑर्डर _ आईडी # स्टेप', 'saga _ id # n'। हैंडलर:- जाँच "पहले से देखा गया है?" - TTL/Retsch के साथ Dedup-stor (Redis/DB)।
- यदि आपने देखा, तो पहले से गणना किए गए परिणाम को दोहराता है या नो-ऑप करता है।
lua
-- SET key if not exists; expires in 24h local ok = redis.call("SET", KEYS[1], ARGV[1], "NX", "EX", 86400)
if ok then return "PROCESS" else return "SKIP" end
4. आधार में 2 अपसर्ट (पहचानने वाला सिंक)
संस्करण/राशि जाँच के साथ UPSERT/ON CONPLAST के माध्यम से प्रविष्टियाँ बनाई जा
PostgreSQL:sql
INSERT INTO payments(id, status, amount, updated_at)
VALUES ($1, $2, $3, now())
ON CONFLICT (id) DO UPDATE
SET status = EXCLUDED.status,
updated_at = now()
WHERE payments.status <> EXCLUDED.status;
4. 3 लेन-देन आउटबॉक्स/इनबॉक्स
आउटबॉक्स: एक व्यावसायिक लेनदेन और एक घटना-से-प्रकाशन प्रविष्टि एक ही डेटाबेस लेनदेन में होती है। पृष्ठभूमि प्रकाशक आउटबॉक्स पढ़ ता है और ब्रोकर को भेजता है - राज्य और घटना के बीच कोई विसंगति नहीं है।
इनबॉक्स: आने वाले कमांड के लिए, 'संदेश _ id' और परिणाम को निष्पादन से पहले सहेजें; पुनर्संसाधन रिकॉर्ड देखता है और दुष्प्रभावों को दोहराता नहीं है।
4. 4 सुसंगत श्रृंखला प्रसंस्करण (read→process→write)
काफ्का: लेनदेन "ऑफसेट पढ़ें - एक परमाणु ब्लॉक में प्रतिबद्धता के परिणामों को लिखा"।
लेनदेन के बिना: "पहले परिणाम/इनबॉक्स, फिर ack" लिखें; दुर्घटना के साथ, डुप्लिकेट इनबॉक्स देखेगा और नो-ऑप के साथ समाप्त होगा।
4. 5 SAGA/ऑफसेट
जब पहचान असंभव होती है (बाहरी प्रदाता ने पैसे से लिखा), हम क्षतिपूर्ति संचालन (वापसी/शून्य) का उपयोग करते हैं और बाहरी एपीआई (एक ही 'आइडेम्पोटेंसी-की' के साथ दोहराया 'पोस्ट' एक ही परिणाम देता है)।
5) जब कम से कम एक बार पर्याप्त हो
कुंजी-आधारित संघनन के साथ कैश/भौतिक विचारों के अपडेट।
काउंटर/मीट्रिक जहां पुन: वृद्धि स्वीकार्य है (या संस्करण के साथ डेल्टा स्टोर करें)।
सूचनाएं जहां द्वितीयक अक्षर महत्वपूर्ण नहीं है (वैसे भी कुंजी लगाना बेहतर है)।
नियम: यदि डबल व्यावसायिक अर्थ को नहीं बदलता है या हम आसानी से पा सकते हैं - कम से कम एक बार + आंशिक सुरक्षा।
6) प्रदर्शन और लागत
बिल्कुल एक बार (यहां तक कि "प्रभावी") की लागत अधिक होती है: अतिरिक्त रिकॉर्ड (इनबॉक्स/आउटबॉक्स), स्टोरिंग कुंजी, लेनदेन, निदान अधिक कठिन होते हैं।
कम से कम एक बार सस्ता/सरल है, थ्रूपुट/p99 पर बेहतर है।
मूल्यांकन: सुरक्षा की दोहरी बनाम लागत की दोहरी × संभावना की कीमत।
7) नमूना विन्यास और कोड
7. 1 काफ्का निर्माता (पहचान + लेनदेन)
properties enable.idempotence=true acks=all retries=INT_MAX max.in.flight.requests.per.connection=5 transactional.id=orders-writer-1
java producer.initTransactions();
producer.beginTransaction();
producer.send(recordA);
producer.send(recordB);
// также можно atomically commit consumer offsets producer.commitTransaction();
7. 2 इनबॉक्स कंसोल (छद्म कोड)
pseudo if (inbox.exists(msg.id)) return inbox.result(msg.id)
begin tx if!inbox.insert(msg.id) then return inbox.result(msg.id)
result = handle(msg)
sink.upsert(result) # идемпотентный синк inbox.set_result(msg.id, result)
commit ack(msg)
7. 3 HTTP Idempotency-Key (बाहरी API)
POST /payments
Idempotency-Key: 7f1c-42-...
Body: { "payment_id": "p-123", "amount": 10.00 }
एक ही कुंजी के साथ दोहराया POST - एक ही परिणाम/स्थिति।
8) अवलोकन और मैट्रिक्स
'डुप्लिकेट _ प्रयास _ टोटल' - कितनी बार एक डबल पकड़ा गया (इनबॉक्स/रेडिस के अनुसार)।
'idempotency _ hit _ rate' - idempotency द्वारा "सहेजे गए" पुनरावृत्तियों का अनुपात।
'txn _ abort _ rate' (काफ्का/डीबी) - रोलबैक का हिस्सा।
'outbox _ backlog' - प्रकाशन अंतराल।
'exacty _ one _ path _ latency {p95, p99}' vs 'at _ less _ one _ path _ latency' - overhead।
लेखा परीक्षा लॉग: 'संदेश _ id', 'idempotency _ key', 'saga _ id', 'प्रयास' का एक समूह।
9) टेस्ट प्लेबुक (गेम डेज़)
रिप्ले भेजें: निर्माता कृत्रिम समय के साथ पुनः प्राप्त करता है।
"सिंक और एक" के बीच क्रैश: सुनिश्चित करें कि इनबॉक्स/अपसर्ट एक डबल को रोकें।
पुन: वितरण: दलाल में पुनर्वितरण में वृद्धि; dedup की जाँच करें।
बाहरी एपीआई की पहचान: एक ही कुंजी के साथ दोहराया POST एक ही उत्तर है।
लीड चेंज/नेटवर्क ब्रेक: काफ्का लेनदेन/उपभोक्ता व्यवहार की जाँच करें।
10) एंटी-पैटर्न
परिवहन पर भरोसा करें: "हमारे पास काफ्का बिल्कुल एक बार है, इसलिए आप बिना कुंजी के" - नहीं।
रिकॉर्डिंग से पहले नो-ऑप एक्क: ackled लेकिन सिंक गिर गया → नुकसान।
DLQ/जिटर रिट्रीट की कमी: अंतहीन रिप्ले और तूफान।
प्राकृतिक कुंजी के बजाय यादृच्छिक यूयूआईडी: डीडुप्लिकेट करने के लिए कुछ नहीं।
इंडेक्स-फ्री प्रोडक्शन टेबल के साथ इनबॉक्स/आउटबॉक्स मिलाना: हॉट लॉक और p99 टेल।
बाहरी प्रदाताओं पर पहचान एपीआई के बिना व्यावसायिक लेनदेन।
11) चयन जाँच सूची
1. दोहरी कीमत (धन/कानूनी/UX) बनाम सुरक्षा मूल्य (विलंबता/जटिलता/लागत)।
2. क्या कोई प्राकृतिक घटना/ऑपरेशन कुंजी है? यदि नहीं, तो एक स्थिर के साथ आओ।
3. सिंक Upsert/versioning का समर्थन करता है? अन्यथा - इनबॉक्स + मुआवजा।
4. क्या आपको वैश्विक लेनदेन की आवश्यकता है यदि नहीं, तो SAGA में खंड।
5. रिप्ले/लंबे प्रतिधारण की आवश्यकता है? काफ्का + आउटबॉक्स। तेज आरपीसी/कम विलंबता की आवश्यकता है? NATS + Idempotency-Key।
6. बहु-किरायेदारी और कोटा: कुंजी/अंतरिक्ष अलगाव।
7. अवलोकन: पहचान और बैकलॉग मेट्रिक्स शामिल हैं।
12) एफएक्यू
प्रश्न: क्या "गणितीय" को वास्तव में एक बार एंड-टू-एंड प्राप्त करना संभव है?
A: केवल एक सुसंगत स्टोर और लेनदेन के साथ संकीर्ण परिदृश्यों में। सामान्य मामले में, नहीं; पहचान के माध्यम से प्रभावी रूप से एक बार उपयोग करें।
प्रश्न: कौन सा तेज है?
A: कम से कम एक बार। वास्तव में एक बार लेनदेन/कुंजी भंडारण जोड़ ता है - p99 और लागत से ऊपर।
प्रश्न: पहचान कुंजियों को कहाँ संग्रहीत करें?
A: TTL, या इनबॉक्स टेबल (PK = message _ id) के साथ क्विक स्टॉप (Redis)। भुगतान के लिए - लंबे समय (दिन/सप्ताह)।
प्रश्नः टीटीएल डेडअप कुंजियाँ कैसे चुनें?
A: न्यूनतम = अधिकतम री-डिलीवरी समय + परिचालन मार्जिन (आमतौर पर 24-72 घंटे)। वित्त के लिए - अधिक।
प्रश्न: क्या मुझे काफ्का में कुंजी द्वारा संघनन की आवश्यकता है?
A: हाँ। संपीड़न भंडारण को कम करेगा, लेकिन आपका समन्वयित पहचान नहीं करेगा.
13) कुल
कम से कम-एक बार - बुनियादी, विश्वसनीय परिवहन शब्दार्थ।
एक बार व्यावसायिक प्रभाव के रूप में प्रोसेसर स्तर पर प्राप्त किया जाता है: आइडेम्पोटेंसी-की, इनबॉक्स/आउटबॉक्स, अपसर्ट/संस्करण, एसएजीए/मुआवजा।
विकल्प लागत का एक समझौता है - दोहराव का जोखिम - संचालन में आसानी। प्राकृतिक कुंजियों को डिजाइन करें, चोट के निशान को पहचानें, अवलोकन जोड़ें और नियमित रूप से खेल के दिनों को खेलें - फिर आपकी पाइपलाइनें रेट्रास और विफलताओं के तूफान में भी अनुमानित और सुरक्षित होंगी।