تقسیم رویداد
1) چرا تقسیم بندی
تکراری به نظر می رسد با توجه به retrays، زمان بندی شبکه، شکست و پخش داده های تاریخی. اگر کنترل نشود:- invariants نقض می شود (بدهی های دوگانه، تکرار ایمیل/اس ام اس، دو بار ایجاد شده) ؛
- افزایش هزینه ها (بازنویسی/پردازش مجدد)
- تحلیل های تحریف شده
هدف از deduplication است که به ارائه یک اثر مشاهده یک بار با تکرار حمل و نقل قابل قبول، اغلب همراه با idemotency.
2) جایی که برای قرار دادن deduplication (سطوح)
1. دروازه لبه/API - تکرار صریح را با «Idempotency-Keu »/بدن + امضا قطع کنید.
2. کارگزار/جریان - deduplication منطقی توسط کلید/دنباله، coalescing در یک دست (کمتر - با توجه به هزینه).
3. گیرنده رویداد (مصرف کننده) - محل اصلی: صندوق ورودی/جدول کلید/کش.
4. سینک (DB/cache) - کلیدهای منحصر به فرد/UPSERT/نسخه/فشرده سازی.
5. ETL/تجزیه و تحلیل - مهلت توسط پنجره زمان و کلید در تخت ستون.
قانون: در اسرع وقت، اما با در نظر گرفتن هزینه مثبت کاذب و نیاز به پخش مجدد.
3) کلید های تقسیم
3. 1 طبیعی (ترجیح داده شده)
«payment _ id»، «order _ id»، «saga _ id #step»، «aggregate _ id #seq».
ثبات و معنی را تضمین می کند.
3. 2 کامپوزیت
'( ، نوع، ، نسخه)' '( ، )'.
3. 3 اثر انگشت
هش یک زیر مجموعه قطعی از زمینه ها (عادی سازی نظم/ثبات ها)، به صورت اختیاری 'HMAC (راز، بار)'.
3. 4 توالی/نسخه
یکنواخت 'seq' per aggregate (بلوک خوش بینانه/نسخه).
ضد الگو: «UUID تصادفی» بدون ارتباط با یک نهاد تجاری غیرممکن است.
4) پنجره های زمان و سفارش
پنجره Deduplication - دوره ای که در طی آن رویداد می تواند دوباره (معمولا 24-72 ساعت ؛ برای امور مالی - طولانی تر).
خارج از نظم: بیایید تاخیر داشته باشیم. در چارچوب های جریان - زمان رویداد + علامت های سفید.
کشویی/رفع پنجره مرده: "آیا کلید را در آخرین N دقیقه دیده اید ؟ ».
Sequence-aware: اگر «seq» آخرین پردازش ≤ - دو برابر/تکرار.
5) ساختار داده ها و پیاده سازی
5. 1 حسابداری دقیق
Redis SET/STRING + TTL: 'کلید SETNX 1 EX 86400' → «برای اولین بار - ما در حال پردازش هستیم، در غیر این صورت - SKIP».
حافظه نهان LRU/LFU (in-proc): سریع، اما فرار → بهتر فقط به عنوان اولین مانع.
شاخص های منحصر به فرد SQL + UPSERT: «درج یا به روز رسانی» (اثر idempoint).
5. ۲ ساختارهای تقریبی (احتمالاتی)
فیلتر بلوم/فاخته: حافظه ارزان، مثبت کاذب امکان پذیر است. این برای یک قطره واضح «پر سر و صدا» (به عنوان مثال، تله متری) مناسب است، نه برای امور مالی/سفارشات.
Count-Min Sketch: تخمین فرکانس ها برای محافظت در برابر «داغ» طول می کشد.
5. 3 کشورهای جریان
جریان کافکا/فلینک: فروشگاه دولتی کلید با TTL، dedup توسط کلید در پنجره ؛ بازرسی/بازیابی.
علامت + تاخیر مجاز: پنجره رویدادهای اواخر را مدیریت می کند.
6) الگوهای معاملاتی
6. 1 صندوق ورودی (جدول ورودی)
Save 'message _ id '/key و در نتیجه عوارض جانبی:pseudo
BEGIN;
ins = INSERT INTO inbox(id, received_at) ON CONFLICT DO NOTHING;
IF ins_not_inserted THEN RETURN cached_result;
result = handle(event);
UPSERT sink with result; -- idempotent sync
UPDATE inbox SET status='done', result_hash=... WHERE id=...;
COMMIT;
بازپخش ضبط را خواهد دید و اثر را تکرار نخواهد کرد.
6. 2 صندوق پستی
رکورد کسب و کار و رویداد در یک معامله → ناشر به کارگزار می فرستد. دوگانه را از مصرف کننده حذف نمی کند، اما «سوراخ ها» را حذف می کند.
6. 3 شاخص های منحصر به فرد/UPSERT
sql
INSERT INTO payments(id, status, amount)
VALUES ($1, $2, $3)
ON CONFLICT (id) DO NOTHING; -- "create once"
یا ارتقاء نسخه کنترل شده:
sql
UPDATE orders
SET status = $new, version = version + 1
WHERE id=$id AND version = $expected; -- optimistic blocking
6. 4 نسخه از مصالح
این رویداد قابل اجرا است اگر "رویداد. version = مجموع نسخه + 1 در غیر این صورت - دو برابر/تکرار/درگیری.
7) مرده و کارگزاران/جریان
7. 1 کافکا
Idempotent Producer دو برابر شدن ورودی را کاهش می دهد.
معاملات به شما اجازه می دهد تا به صورت اتمی مرتکب آفست + سوابق خروجی شوید.
تراکم: آخرین مقدار در هر کلید را ذخیره می کند - post-factum dedup/coalescing (نه برای پرداخت).
سمت مصرف کننده: فروشگاه دولتی/Redis/DB برای کلیدهای پنجره.
7. 2 NATS/جت جریان
Ack/redelivery → حداقل یک بار. Dedup در مصرف کننده (صندوق ورودی/Redis).
توالی JetStream/کار مصرف کننده، شناسایی تکرارها را آسان تر می کند.
7. 3 صف (خرگوش/SQS)
زمان مشاهده + تحویل مکرر → شما نیاز به یک کلید + deadstore.
SQS FIFO با 'MessageGroupId '/' DeduplicationId' کمک می کند، اما ویندوز TTL ارائه دهنده محدود است - نگه داشتن کلید دیگر اگر کسب و کار نیاز دارد.
8) ذخیره سازی و تجزیه و تحلیل
8. 1 کلیکخانه/بزرگ پرس و جو
Dedup توسط پنجره: «ترتیب کلید، ts» و «argMax »/« anyLast» با شرایط.
کلیک خانه:sql
SELECT key,
anyLast(value) AS v
FROM t
WHERE ts >= now() - INTERVAL 1 DAY
GROUP BY key;
یا یک لایه تحقق یافته از رویدادهای «منحصر به فرد» (ادغام با کلید/نسخه).
8. 2 سیاهههای مربوط/تله متری
بیایید می گویند تقریبی دامپ (بلوم) در مصرف → صرفه جویی در شبکه/دیسک.
9) پردازش مجدد، پخش و پر کردن مجدد
کلیدهای Dedup باید در بازپخش زنده بمانند (پنجره بازپخش ≥ TTL).
برای پر کردن مجدد، از فضای کلید با نسخه («key # source = batch2025») استفاده کنید یا «نشت» را جدا کنید تا در پنجره آنلاین دخالت نکنید.
مصنوعات نتیجه فروشگاه (هش/نسخه) - این سرعت «سریع جست و خیز» در تکرار.
10) معیارها و قابلیت مشاهده
'dedup _ hit _ total '/' dedup _ hit _ rate' - نسبت تکراری گرفتار شده است.
'dedup _ fp _ rate' برای فیلترهای احتمالاتی
'window _ size _ seconds' واقعی (با تله متری در اواخر ورود).
'inbox _ conflict _ total', 'upsert _ conflict _ total'.
'replayed _ events _ total', 'skipped _ by _ inbox _ total'.
پروفایل های مستاجر/کلید/نوع: که در آن بیشتر طول می کشد و چرا.
Логи: 'message _ id', 'idempotency _ key', 'seq', 'window _ id', 'action = process' skip '.
11) امنیت و حریم خصوصی
PII را در کلید قرار ندهید از hashes/aliases استفاده کنید.
برای امضای اثر انگشت - HMAC (مخفی، canonical_payload) برای جلوگیری از برخورد/جعل.
هماهنگی زمان ذخیره سازی کلید با انطباق (حفظ GDPR).
12) عملکرد و هزینه
In-proc LRU ≪ Redis SQL را با تأخیر/هزینه در هر عملیات ≪ می کند.
Redis: ارزان و سریع است، اما حجم کلید و TTL را در نظر بگیرید ؛ shardy توسط 'مستاجر/هش'.
SQL: گران قیمت توسط p99، اما تضمین های قوی و مخاطبان را فراهم می کند.
فیلترهای احتمالی: بسیار ارزان هستند، اما FP ها امکان پذیر هستند - استفاده از جایی که «SKIP اضافی» حیاتی نیست.
13) ضد الگوهای
ما کافکا را دقیقاً یک بار داریم، بدون نیاز به کلید. "مورد نیاز - در یک لایه کبودی/کسب و کار.
بیش از حد کوتاه TTL برای کلید → تکرار/تاخیر یک دو برابر تحویل.
جهانی تک dedup → کانون و SPOF ؛ توسط مستاجر/کلید مشترک نیست.
Dedup تنها در حافظه - از دست دادن فرآیند = موج از طول می کشد.
بلوم برای پول/سفارشات - مثبت کاذب عملیات مشروع را محروم خواهد کرد.
canonization payload متناقض - هش های مختلف برای پیام هایی که در معنی یکسان هستند.
نادیده گرفتن خارج از نظم - حوادث اواخر با تکراری اشتباه مشخص شده اند.
14) چک لیست پیاده سازی
- تعریف یک کلید طبیعی (یا ترکیب/اثر انگشت).
- پنجره dedup و سیاست «lateness» را تنظیم کنید.
- سطح (های) را انتخاب کنید: لبه، مصرف کننده، سینک ؛ فراهم می کند برای shardening.
- پیاده سازی صندوق ورودی/UPSERT ؛ برای جریان - حالت کلید + TTL.
- اگر شما نیاز به یک مانع تقریبی - بلوم/فاخته (فقط برای حوزه های غیر بحرانی).
- پیکربندی سازگاری پخش (TTL ≥ پنجره پخش/backfill).
- معیارهای 'dedup _ hit _ rate'، درگیری ها و وقفه های پنجره ؛ داشبورد در هر مستاجر.
- روز بازی: مدت زمان/retrays، پخش، خارج از سفارش، افت حافظه پنهان.
- Canonization بارگیری سند و نسخه بندی کلیدی.
- انجام تست بار بر روی کلید های داغ و پنجره های طولانی.
15) تنظیمات نمونه/کد
15. 1 Redis SETNX + TTL (مانع)
lua
-- KEYS[1] = "dedup:{tenant}:{key}"
-- ARGV[1] = ttl_seconds local ok = redis. call("SET", KEYS[1], "1", "NX", "EX", ARGV[1])
if ok then return "PROCESS"
else return "SKIP"
end
15. 2 صندوق پستی PostgreSQL
sql
CREATE TABLE inbox (
id text PRIMARY KEY,
received_at timestamptz default now(),
status text default 'received',
result_hash text
);
-- In the handler: INSERT... ON CONFLICT DO NOTHING -> check, then UPSERT in blue.
15. 3 جریان کافکا
java var deduped = input
.selectKey((k,v) -> v.idempotencyKey())
.groupByKey()
.windowedBy(TimeWindows. ofSizeWithNoGrace(Duration. ofHours(24)))
.reduce((oldV,newV) -> oldV) // first wins
.toStream()
.map((wKey,val) -> KeyValue. pair(wKey. key(), val));
15. 4 فلینک (حالت کلید + TTL، شبه)
java
ValueState<Boolean> seen;
env. enableCheckpointing(10000);
onEvent(e):
if (!seen.value()) { process(e); seen. update(true); }
15. 5 دروازه NGINX/API (Idempotency-Key در لبه)
nginx map $http_idempotency_key $idkey { default ""; }
Proxy the key to the backend; backend solves deadup (Inbox/Redis).
16) سوالات متداول
س: چه چیزی را انتخاب کنید: deadup یا idempotence خالص ؟
A: معمولا هر دو: deadup یک فیلتر سریع (صرفه جویی) است، idempotence تضمین اثر صحیح است.
س: کدام TTL برای قرار دادن ؟
A: ≥ حداکثر زمان تحویل مجدد + موجودی. به طور معمول 24-72 ساعت ؛ برای امور مالی و وظایف معوق - روزها/هفته ها.
س: چگونه رویدادهای دیر را مدیریت می کنید ؟
A: پیکربندی «تأخیر مجاز» و alarm «late _ event» ؛ آنهایی که بعد - از طریق یک شاخه جداگانه (محاسبه/جست و خیز).
س: آیا می توان کل جریان تله متری را تقسیم کرد ؟
A: بله، فیلترهای تقریبی (بلوم) در لبه، اما FP را در نظر بگیرید و به اثرات کسب و کار بحرانی اعمال نمی شود.
س: Deadup گرفتن در راه backfill ؟
A: جدا کردن فضاهای کلیدی ('key # batch2025') یا غیر فعال کردن مانع برای مدت زمان backfill ؛ کلیدهای TTL فقط باید پنجرههای آنلاین را پوشش دهند.
17) مجموع
Deduplication ترکیب است: کلید سمت راست، پنجره و ساختار دولت + الگوهای معاملاتی (صندوق ورودی/صندوق خروجی/UPSERT) و دست زدن به ذهن نظم و حوادث اواخر. موانع را در جایی که ارزان تر است قرار دهید، اطمینان حاصل کنید که idempotence در کبودی، اندازه گیری «dedup _ hit _ rate» و تست مجدد/شکست - به این ترتیب شما «به طور موثر دقیقا یک بار» بدون دم های غیر ضروری از تاخیر و هزینه.