GH GambleHub

Deduplikacja zdarzeń

1) Dlaczego deduplikowanie

Duplikaty pojawiają się ze względu na przekaźniki, timeouts sieci, awaria i powtórzenie danych historycznych. Jeżeli nie są kontrolowane:
  • osoby niezmienne są naruszane (podwójne obciążenia, powtarzające się wiadomości e-mail/SMS, „dwukrotnie utworzone”);
  • Wzrost kosztów (ponowne zapisy/przeróbki)
  • zniekształcona analityka.

Celem deduplikowania jest zapewnienie jednorazowego obserwowanego efektu z możliwymi do zaakceptowania powtórzeniami transportowymi, często wraz z idempotencją.

2) Gdzie umieścić deduplikowanie (poziomy dokładności)

1. Brama krawędzi/API - odcięcie wyraźnych duplikatów przez 'Idempotency-Keu '/body + signature.
2. Broker/stream - logiczne deduplication by key/sequence, coalescing at a miss (rzadziej - ze względu na koszty).
3. Odbiornik zdarzeń (konsument) - główna lokalizacja: skrzynka odbiorcza/tabela klucza/pamięć podręczna.
4. Zlewozmywak (DB/cache) - unikalne klucze/UPSERT/wersje/kompresja.
5. ETL/analysis - deadline by time window and key in column beds.

Zasada: jak najwcześniej, ale biorąc pod uwagę koszt fałszywych pozytywów i potrzebę powtórzenia.

3) Klucze deduplikacji

3. 1 Naturalne (preferowane)

'payment _ id',' order _ id', 'saga _ id # step', 'aggregate _ id # seq'.
Gwarantuje stabilność i znaczenie.

3. 2 Złożony

„(tenant_id, typ, external_id, wersja)” ила „(user_id, event_ts_truncated, payload_hash)”.

3. 3 Odcisk palca

Hash deterministycznego pola (normalizować kolejność/rejestry), opcjonalnie „HMAC (secret, payload)”.

3. 4 sekwencje/wersje

Monotonny kruszywo 'seq' per (optymistyczne blokowanie/wersioning).

Anty-wzór: „losowy UUID” bez połączenia z podmiotem gospodarczym jest niemożliwe.

4) Okna czasowe i zamówienie

Okno deduplikacji - okres, w którym zdarzenie może powtórzyć się (zwykle 24-72 godziny; dla finansów - dłużej).
Nieporządek: bądźmy spóźnieni. W ramach strumieniowych - czas imprezy + znaki wodne.
Sliding/Fix-window deadup: "Czy widziałeś klucz w ostatnich minutach N? ».
Sequence-aware: jeżeli 'seq' ≤ ostatni przetworzony - double/repeat.

5) Struktury i implementacje danych

5. 1 Dokładna księgowość

Redis SET/STRING + TTL: 'SETNX key 1 EX 86400' → 'po raz pierwszy - przetwarzamy, inaczej - SKIP'.
Pamięć podręczna LRU/LFU (in-proc): szybka, ale lotna → lepsza tylko jako pierwsza bariera.
Unikalne indeksy SQL + UPSERT: „wstawić lub zaktualizować” (efekt idempotentny).

5. 2 Przybliżone struktury (probabilistyczne)

Filtr Bloom/Cuckoo: tania pamięć, fałszywe pozytywy są możliwe. Nadaje się do oczywistego „hałaśliwego” spadku (na przykład telemetrii), a nie do finansowania/zamówień.
Count-Min Sketch: Oszacowanie częstotliwości do ochrony przed „gorącym” bierze.

5. 3 Państwa przesyłania strumieniowego

Kafka Streams/Flink: keyed state store z TTL, dedup by key in the window; punkt kontrolny/przywrócenie.
Znak wodny + dozwolone opóźnienie: Zarządza późnym oknem zdarzeń.

6) Wzorce transakcyjne

6. 1 Skrzynka odbiorcza (tabela przychodząca)

Zapisz 'message _ id'/klucz i wynik do efektów ubocznych:
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;

Powtórka zobaczy nagranie i nie powtórzy efektu.

6. 2 Skrzynka zewnętrzna

Rekord biznesowy i wydarzenie w jednej transakcji → wydawca wysyła do brokera. Nie eliminuje podwójnego z konsumenta, ale wyklucza „dziury”.

6. 3 Niepowtarzalne indeksy/UPSERT

sql
INSERT INTO payments(id, status, amount)
VALUES ($1, $2, $3)
ON CONFLICT (id) DO NOTHING; -- "create once"
lub uaktualnienie wersji kontrolowanej:
sql
UPDATE orders
SET status = $new, version = version + 1
WHERE id=$id AND version = $expected; -- optimistic blocking

6. 4 Wersioning kruszyw

Zdarzenie ma zastosowanie, jeśli "zdarzenie. wersja = agregat. wersja + 1 '. W przeciwnym razie - podwójny/powtarzający się/konflikt.

7) Deadup i brokerów/strumieni

7. 1 Kafka

Idempotent Producent zmniejsza podwójne wejście.
Transakcje pozwalają na atomowe dokonywanie przesunięć + rekordów wyjściowych.
Zagęszczenie: przechowuje ostatnią wartość na klucz - dedup/koalescing (nie dla płatności).
Strona konsumencka: sklep stanowy/Redis/DB dla kluczy okiennych.

7. 2 NATS/JetStream

Ack/redelivery → co najmniej raz. Dedup w konsument (skrzynka odbiorcza/Redis).
Sekwencja JetStream/praca konsumencka ułatwia identyfikację powtórzeń.

7. 3 kolejki (Królik/SQS)

Wyprzedaż widzialności + wielokrotne dostawy → potrzebujesz klucza + deadstore.
Funkcja SQS FIFO z funkcją „ GroupId ”/„ Dedupl, Id” pomaga, ale okna TTL są ograniczone przez dostawcę - utrzymać klucze dłużej, jeśli wymaga tego biznes.

8) Magazynowanie i analizatory

8. 1 Kliknij Dom/Zapytanie

Dedup przez okno: 'ORDER BY key, ts' i' argMax '/' anyLast 'z warunkiem.

ClickHouse:
sql
SELECT key,
anyLast(value) AS v
FROM t
WHERE ts >= now() - INTERVAL 1 DAY
GROUP BY key;

Lub zmaterializowana warstwa „unikalnych” zdarzeń (połączenie przez klucz/wersja).

8. 2 Kłody/telemetria

Powiedzmy approximate-dump (Bloom) na połknięciu → zapisz sieć/dysk.

9) Ponowne przetwarzanie, powtarzanie i zasypywanie

Klawisze Dedup muszą przetrwać powtórkę (TTL ≥ okno powtórzenia).
Dla zasypki, użyj przestrzeni klucza z wersją ('key # source = batch2025') lub oddzielnych „przecieków”, aby nie zakłócać okna online.
Zapisz wyniki artefaktów (hash/wersja) - przyspiesza to „szybkie pomijanie” na powtórkach.

10) Metryka i obserwowalność

'dedup _ hit _ total '/' dedup _ hit _ rate' - odsetek złowionych duplikatów.
'dedup _ fp _ rate' dla filtrów probabilistycznych.
„window _ size _ seconds” (według późnych przylotów telemetrycznych).
'inbox _ conflict _ total', 'upsert _ conflict _ total'.
„replayed _ events _ total”, „skipped _ by _ inbox _ total”.
Profile według najemcy/klucza/typu: gdzie są najbardziej wzięte i dlaczego.

Лова: 'message _ id',' idempotency _ key ',' seq ',' window _ id', 'action = process' skip '.

11) Bezpieczeństwo i prywatność

Nie umieszczać PII w kluczu; używać hashes/aliasów.
Aby podpisać odcisk palca - HMAC (secret, canonical_payload), aby uniknąć kolizji/fałszerstwa.
Koordynacja czasu przechowywania kluczy z zachowaniem zgodności (RODO).

12) Wydajność i koszt

In-proc LRU Redis SQL według opóźnienia/kosztu na operację.
Redis: tanie i szybkie, ale rozważyć objętość klawiszy i TTL; shardy przez 'lokator/hash'.
SQL: drogie przez p99, ale zapewnia silne gwarancje i publiczność.
Filtry probabilistyczne: bardzo tanie, ale FP są możliwe - użyj tam, gdzie „dodatkowe SKIP” nie jest krytyczne.

13) Anty-wzory

"Mamy Kafkę dokładnie raz - nie jest potrzebny klucz. "Potrzebne - w siniaku/warstwie biznesowej.
Zbyt krótki TTL dla kluczy → powtórki/opóźnienie dostarczy podwójne.
Global single dedup → hotspot i SPOF; nie strzelane przez najemcę/klucz.
Dedup tylko w pamięci - utrata procesu = fala zabierania.
Kwitnie za pieniądze/zamówienia - fałszywie pozytywne pozbawi legalną operację.
Niespójna kanonizacja ładunku - różne hashes dla wiadomości, które są identyczne w znaczeniu.
Ignorowanie out-of-order - późne wydarzenia są oznaczone duplikatami błędnie.

14) Lista kontrolna wdrażania

  • Zdefiniować klucz naturalny (lub złożony/odcisk palca).
  • Ustaw okno dedup i politykę „nieprzewidywalności”.
  • Wybierz poziom (-y): krawędź, konsument, zlewozmywak; zapewnić ostrzenie.
  • Wdrożenie skrzynki odbiorczej/UPSERT; dla przepływów - stan kluczowy + TTL.
  • Jeśli potrzebujesz przybliżonej bariery - Bloom/Cuckoo (tylko dla domen niekrytycznych).
  • Konfiguracja kompatybilności powtórki (TTL ≥ okno powtórzenia/zasypki).
  • Wskaźniki „dedup _ hit _ rate”, konflikty i opóźnienia okienne; deski rozdzielcze dla jednego najemcy.
  • Dzień gry: timeouts/retrays, replay, out-of-order, cache drop.
  • Kanonizacja ładunku dokumentów i wersioning kluczy.
  • Wykonaj testy obciążenia klawiszy gorących i długich okien.

15) Konfiguracje próbki/Kod

15. 1 Redis SETNX + TTL (bariera)

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 Skrzynka odbiorcza 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 strumienie Kafka

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 Flink (stan kluczowy + TTL, pseudo)

java
ValueState<Boolean> seen;
env. enableCheckpointing(10000);
onEvent(e):
if (!seen.value()) { process(e); seen. update(true); }

15. Brama 5 NGINX/API (Idempotency-Key na krawędzi)

nginx map $http_idempotency_key $idkey { default ""; }
Proxy the key to the backend; backend solves deadup (Inbox/Redis).

16) FAQ

P: Co wybrać: deadup lub czysta idempotencja?
Odp.: Zwykle zarówno: deadup jest szybkim „filtrem” (oszczędności), idempotencja jest gwarancją prawidłowego efektu.

P: Który TTL umieścić?
Odp.: ≥ maksymalny możliwy czas ponownej dostawy + inwentaryzacja. Zazwyczaj 24-72 godziny; dla zadań finansowych i odroczonych - dni/tygodnie.

P: Jak radzisz sobie z późnymi wydarzeniami?
A: Skonfigurować 'dozwolone opóźnienie' i 'late _ event' alarm'; później - przez oddzielną gałąź (recompute/skip).

P: Czy cały strumień telemetryczny może zostać zdublowany?
Odp.: Tak, przybliżone filtry (Bloom) na krawędzi, ale rozważyć FP i nie mają zastosowania do krytycznych efektów biznesowych.

P: Deadup staje na drodze zasypki?
Odp.: Oddzielne klucze ('klucz # batch2025') lub wyłączyć barierę na czas zasypki; Klucze TTL powinny obejmować tylko okna online.

17) Kwoty całkowite

Deduplikacja to kompozycja: odpowiedni klucz, struktura okna i stanu + wzorce transakcyjne (Inbox/Outbox/UPSERT) oraz świadome obsługiwanie zamówień i późnych zdarzeń. Umieść bariery, gdzie jest najtańszy, zapewnić idempotencję w siniakach, zmierzyć 'dedup _ hit _ rate' i powtórki testowe/niepowodzenia - w ten sposób otrzymasz „skutecznie dokładnie raz” bez zbędnych ogonów opóźnienia i kosztów.

Contact

Skontaktuj się z nami

Napisz do nas w każdej sprawie — pytania, wsparcie, konsultacje.Zawsze jesteśmy gotowi pomóc!

Rozpocznij integrację

Email jest wymagany. Telegram lub WhatsApp są opcjonalne.

Twoje imię opcjonalne
Email opcjonalne
Temat opcjonalne
Wiadomość opcjonalne
Telegram opcjonalne
@
Jeśli podasz Telegram — odpowiemy także tam, oprócz emaila.
WhatsApp opcjonalne
Format: kod kraju i numer (np. +48XXXXXXXXX).

Klikając przycisk, wyrażasz zgodę na przetwarzanie swoich danych.