معانی دقیق یک بار
آنچه دقیقا یک بار واقعا است
«دقیقا یک بار» اغلب به معنای دو چیز متفاوت است:- تحویل: پیام دقیقا یک بار به مصرف کننده تحویل داده می شود.
- پردازش: اثر جانبی نهایی (نوشتن به پایگاه داده، تغییر تعادل، صدور یک رویداد دیگر) دقیقا یک بار اتفاق خواهد افتاد، حتی اگر تحویل یا تلاش بیشتری وجود داشته باشد.
در سیستم های توزیع شده، صحبت کردن در مورد معانی پردازش قابل اطمینان تر است. تحویل دقیقا یک بار دشوار است (تکراری و تکراری اجتناب ناپذیر است)، اما حالت حاصل می تواند معادل یک درمان واحد باشد.
چه زمانی EOS مورد نیاز است و چه زمانی نیست
EOS مورد نیاز است اگر:- معاملات نقدی و تعادل: دوبار نوشتن مجاز نیست.
- حسابداری مجوز/سهمیه، شمارنده صورتحساب.
- تماس های خارجی برگشت ناپذیر (به عنوان مثال، فعال سازی کلید یک بار).
- اثرات برگشت پذیر یا جبران پذیر هستند (sagas، returns).
- تکراری موقت در فروشگاه ها/سیاهههای مربوط مجاز است.
- ارائه یک سینک بی نظیر ارزان تر از کشیدن معاملات از طریق کل مسیر است.
مدل: پایان به پایان در مقابل هاپ توسط هاپ
Hop-by-hop EOS: هر بخش (منبع → پردازنده → گیرنده) تضمین می کند که عمل خود را دقیقا یک بار اعمال می کند.
پایان دادن به پایان EOS: کل زنجیره تضمین می کند که از «واقعیت» به «اثر جانبی»، نتیجه معادل یک درمان واحد است.
در عمل، پایان دادن به پایان با ترکیبی از معاملات و/یا idempotency در هر هاپ به دست می آید.
بلوک های پایه ساختمان
1. عملیات بی نظیر
تکرار همان پرس و جو در کلید عملیات همان نتیجه را تولید می کند.
Ключи: 'idempotency _ key '/' event _ id '/' operation _ id'.
پیاده سازی: جدول عملیات «دیده شده» با TTL ≥ ارائه ورودی ورودی.
2. تراکنشهای خواندن-پردازش-نوشتن
در یک واحد اتمی از کار، هر دو اثر جانبی و پیشرفت خواندن (آفست/موقعیت) ثبت شده است. این «ارواح» را هنگام افتادن بین پله ها از بین می برد.
3. نسخه/توالی
یک نسخه/شمارنده برای مجموع ذخیره می شود ؛ تغییرات فقط در صورتی اعمال میشوند که 'expected _ version' مطابقت داشته باشد. تکرارهای همان رویداد، نسخهٔ → اثر را یک بار افزایش نمیدهند.
4. تقسیم بندی
فهرست در «(consumer_id، event_id)» یا در «business _ id» طبیعی معامله.
الگوهای پیاده سازی
1) ورود به سیستم معاملاتی + سینک معامله با تثبیت افست
ایده آل برای پردازش جریان.
ما از ورود به سیستم (فقط نوشته های تایید شده) را بخوانید.
ما پردازش را انجام می دهیم.
- الف) اثر را در سینک بنویسید (پایگاه داده/جدول)،
- ب) ثابت «خواندن برای جبران N» (در همان پایگاه داده).
- قول بده هنگام راه اندازی مجدد، یا همه چیز تخفیف داده می شود (و افست تغییر می کند)، یا هیچ چیز.
خواص: اجرای مکرر مضر نیست ؛ «دقیقا یک بار»، حتی اگر پیام دو بار خوانده شود.
2) صندوق پستی + مصرف کننده idemotent
برای خدمات تولید کننده معامله.
در یک معامله پایگاه داده: رکورد دامنه را تغییر دهید و رویداد را در صندوق پستی بنویسید.
تکرار کننده رویداد را به اتوبوس با همان «event _ id» ارائه می دهد.
مصرف کنندگان رویدادها را به طور یکنواخت اعمال می کنند (با «event _ id»).
خواص: تولید کننده تضمین می کند هیچ واقعیت از دست داده است ؛ مصرف کنندگان دقیقا یک اثر را تضمین می کنند.
3) EOS در سیستم های کافکا/فلینک مانند (مفهومی)
تولید کننده Idempotent: محافظت در برابر طول می کشد در عقب نشینی ارسال.
معاملات تولید کننده: گروهی از ورودی ها در موضوعات + یک تغییر مصرف کننده به صورت اتمی انجام می شود. خوانندگان از تحلیل متعهدانه استفاده میکنند.
طرف پردازش فروشگاه دولتی را ذخیره می کند و آن را همراه با معامله متعهد می کند.
خواص: دوباره شروع فروشگاه/کشیدن به اثر دو منجر نمی شود ؛ تکراری «قابل مشاهده نیست» پایین دست.
4) «غرق» idempotent از طریق upsert/ادغام
سینک «operation _ id »/« event _ id» را میگیرد و «UPSERT» را اجرا میکند... جایی که وجود ندارد ".
اثر جانبی (به عنوان مثال، تعهدی) به صورت اتمی با چک «قبلا اعمال نشده است» انجام می شود.
خواص: روش EOS ارزان در لبه با ذخیره سازی، بدون معاملات توزیع شده.
جزئیات پیاده سازی کلیدی
شناسه های معامله
باید قطعی برای تکرار می شود (یک UUID جدید تولید نمی هنگام retracting).
یک محدوده پایدار (در مصرف کننده/واحد/سیستم) داشته باشید.
جدول تقسیم بندی
Колонки: 'consumer _ id'، 'operation _ id'، 'applied _ at'، 'ttl _ expires _ at'.
شاخص در '(consumer_id، operation_id).
TTL ≥ پنجره حداکثر تکرار (نگهداری ورود به سیستم + تاخیر بالقوه).
رقابت خوش بینانه
در مدل نوشتن، نسخه واحد را ذخیره کنید.
هنگام اعمال یک رویداد/دستور، از 'WHERE version =: expected'; duplicate نسخه را افزایش نخواهد داد.
سفارش/سفارش
EOS "دقیقا همان سفارش نیست. اطمینان از سازگاری از طریق کلید دسته ای (تمام رویدادهای جمع → یک دسته) و/یا مقایسه «ضریب».
تماس های خارجی بی نظیر
برای روش های ناامن (به عنوان مثال، HTTP webhooks به یک سرویس شخص ثالث)، اضافه کردن «Idempotency-Key» و نیاز به شریک برای حمایت از آن.
تله های مکرر
EOS تنها در یک مکان: اگر سینک بی نظیر باشد، اما شما رویدادهای ثانویه را بدون بی نظمی منتشر می کنید، شما «دقیقا چند بار» در پایین دست دریافت خواهید کرد.
دو تعهد: ابتدا در پایگاه داده، سپس مرتکب افست در کارگزار - سقوط بین آنها اثرات تکراری ایجاد می کند.
CDCs خام: تغییر طرح DB باعث تخریب مصرف کننده می شود.
کلیدهای ناپایدار: 'operation _ id' به زمان/تصادفی و تغییرات در طول بازپخش بستگی دارد.
هزینه و تجارت آف
تاخیر: معاملات/خواندن جداگانه → رشد p95/p99.
ذخیره سازی سربار: جداول deduplication، فروشگاه های دولتی، سیاهههای مربوط به معاملات.
پیچیدگی عملیاتی: زمان بندی معاملات، تعادل موضوع، جلسات گیر کرده است.
تشخیص: حالتهای بیشتر («in kamit», «visible as read_committed,» «rolled back»).
EOS را انتخاب کنید: برای جمع آوری و اثرات بحرانی ؛ پوشش بقیه با idempotency و جبران.
تست دقیقا یک بار
1. تزریق خطا: افت در روند بین مراحل «ثبت اثر» و «ثبت افست».
2. تکراری: همان پیام را 2-5 بار بارگیری کنید، از یک اثر مطمئن شوید.
3. راه اندازی مجدد و توازن: توقف/راه اندازی مجدد کارگران، بررسی عدم وجود پردازش دوگانه.
4. فلاپی های شبکه: زمان های متوسط معامله، ارتکاب مجدد.
5. تست بار: رشد صف → آیا هیچ تخریب به «برای همیشه در معامله» وجود دارد.
قالب های کوتاه (شبه)
سینک ظرفشویی با رفع افست
pseudo begin tx if not exists(select 1 from dedup where consumer_id=:c and op_id=:id)
then apply_effect(...) -- upsert / merge / add_one_time_action insert into dedup(c, id, applied_at) values(:c,:id, now)
end if update offsets set pos=:pos where consumer_id=:c commit
فرمان با نسخه واحد
pseudo begin tx update account set balance = balance +:delta,
version = version + 1 where id=:account_id and version=:expected_version;
if row_count=0 then error CONCURRENT_MODIFICATION commit
ایمنی و انطباق
PII/PCI در جداول deduplication: حداقل ذخیره، استفاده از نشانه ها به جای داده های خام.
حسابرسی: ورود به سیستم 'operation _ id', 'trace _ id', نتیجه (APPLIED/ALREADY_APPLIED).
سیاست ذخیره سازی: TTL در جداول dedup، آرشیو آفست/سیاهههای مربوط.
ضد الگوهای
«تحویل واقعی دقیق یک بار»: تلاش برای حذف تکراری در سطح پروتکل حمل و نقل بدون اثر idempointency.
معاملات توزیع شده جهانی برای همه چیز: XA/2PC از طریق تمام خدمات شکننده و آهسته است.
مخلوط کردن عوارض جانبی غیر idemotent (به عنوان مثال، ایمیل فرستاده شده قبل از تعهد افست).
عدم وجود کلیدهای عملیاتی: با تکیه بر «منحصر به فرد بودن» محموله.
چک لیست تولید
- هر اثر بحرانی دارای یک کلید idempotent.
- موقعیت افست/خواندن در یک معامله با اثر ثابت است.
- جداول تقسیم بندی نمایه شده ؛ TTL ≥ حفظ ورود به سیستم.
- رقابت خوش بینانه (نسخه/دنباله) برای aggregates فعال است.
- موضوعات/موضوعات در حالت «Comp Only» خوانده می شوند (در صورت موجود بودن).
- تست های تکراری و قطره در CI/CD وجود دارد.
- داشبورد: سهم تکرار، معاملات شکست خورده، زمان مسدود کردن، عقب ماندگی.
- مستندات یکپارچه سازی برای 'Idempotency-Key '/retries/timeouts.
سوالات متداول
آیا EOS می تواند بدون معاملات ارائه شود ؟
اغلب بله - از طریق idemotency سینک (upsert/ادغام) و versioning از aggregates. معاملات ضمانت را ساده می کنند اما هزینه را افزایش می دهند.
آیا همه به یک بار نیاز دارند ؟
نه، اينطور نيست خيلي گرونه. درخواست نقطه ای که در آن جبران امکان پذیر نیست/گران است.
چگونه می توان نامه ها/وب سایت ها را با EOS مرتبط کرد ؟
بافر اطلاع رسانی قبل از مرتکب، ارسال پس از تثبیت اثر ؛ «notification _ id» را ذخیره کنید و ارسال را انجام دهید.
چه چیزی مهمتر است - تحویل یا پردازش ؟
در حال پردازش تحویل ممکن است تکرار شود ؛ حالت نهایی باید درست و تنها باشد.
نتیجه گیری
دقیقا یک بار در مورد صحت اثر است، و نه در مورد عدم وجود تکراری در سیم کشی. این است که با ترکیبی از idempotency، تثبیت اتمی از اثر و پیشرفت خواندن، تقسیم معقول و نظم و انضباط نسخه به دست آورد. EOS را اعمال کنید که در آن هزینه خطا غیر قابل قبول است و واقعیت آن را با سقوط و آزمایش می کند - بدون اعتقاد به حمل و نقل.