C. Real-time Antifraud¶
Тип материала: учебный архитектурный сценарий. Не описывает систему конкретной компании.
Границы и предпосылки¶
Kafka4.1 / Flink1.20 → Redis7.4; Redis — serving projection, Flink managed state — источник window computation. Версии Kafka/Flink взяты как reference contracts раздела 01, совместный deployment не проверен. Financial decisions с денежным эффектом требуют authoritative durable transaction. HYPOTHETICAL; модель не описывает систему конкретной компании.
Архитектура¶
Все узлы и связи — HYPOTHETICAL.
flowchart TB
Kafka --> Flink[Keyed state and event-time windows]
Flink --> Checkpoint[Checkpointed state and offsets]
Flink --> FeatureLog[Versioned feature snapshots topic]
FeatureLog --> Sink[Retryable Redis sink]
Sink --> Redis[Versioned TTL feature projection]
Redis --> Decision[Risk decision with completeness policy]
Request[Online requests] --> Limiter[Separate atomic admission ZSET]
Последовательность операций¶
-
Kafka events имеют stable event_id, event time и partition ordering contract. Flink keyBy по tenant/player/device строит окна, задавая watermarks, allowed lateness и duplicate policy. Kafka identity сама по себе не удаляет semantic duplicates producer.
-
Flink state/checkpoints согласуют вычисления и source offsets при настроенном checkpointing. Счётчик не отправляется в Redis как слепой INCR: при повторном sink write это задвоило бы эффект.
-
Сформировать полный feature snapshot с монотонной per-key version и absolute expires_at. Для надёжной публикации feature topic нужен поддерживаемый transactional Kafka sink с его checkpoint contract; иначе explicitly at-least-once и idempotent downstream. Версия не должна сбрасываться после restore.
-
Redis sink вызывает feature-upsert.lua: старые/равные versions игнорируются, TTL задаётся абсолютным deadline. Version хранится как fixed-width decimal string, чтобы избежать потери UInt64 precision в Lua number. JSON payload schema проверяется upstream.
-
Отдельный sliding-window.lua реализует online admission limit через ZSET score=Redis server time, member=request_id. Удаляет scores <= now-window, проверяет duplicate, count, добавляет admitted request и TTL. Все keys одного script здесь — один key, что упрощает Cluster slot scope.
-
Это processing-time rate limit, а не восстановление historical event-time fraud windows. Нормальная работа предполагает контролируемые clock jumps; async failover может потерять admissions. Для hard financial limit использовать authoritative transaction.
-
Decision service читает feature version/window/completeness. При miss/stale/warm-up применяет заранее выбранную policy: manual review, reject либо bounded fallback. Отсутствие key не означает нулевой риск.
Failure modes и recovery¶
| Сбой | Поведение и восстановление |
|---|---|
| Redis write принят, ACK утрачен | Повтор того же version snapshot безопасен при сохранённом version key; INCR был бы опасен. |
| Redis потерял state | Rebuild в новой generation из checkpoint/feature history; переключить readers после completeness barrier. |
| Flink restart/replay | Restore state+offsets; сохранить per-key versions/generation и отфильтровать obsolete windows. |
| Key expired и пришёл stale snapshot | Одна Lua version уже не защищает: version tombstone исчез. Upstream ordering/deadlines/generation policy обязаны не допустить воскрешение. |
| Late event / source retention gap | Allowed lateness policy или quarantine/recompute; если истории нет, отметить UNKNOWN completeness и применить degrade policy. |
Trade-offs и эксплуатация¶
Полный snapshot дороже increment по bytes, зато даёт retry-safe replacement в определённом scope. Redis cache warm-up требует bounded нагрузку и barrier; Cluster не распараллеливает один player key. Dedup admission IDs хранится только внутри окна, это не пожизненная идемпотентность. Lua isolation не rollback и не durable exactly-once.
Код и границы проверки¶
sliding-window.lua и feature-upsert.lua. Lua compiled и выполнены ограниченные model checks command semantics; Redis/Flink/Kafka runtime, Cluster routing и failover не запускались. Модель не доказывает Redis persistence behavior.
Типичные ошибки проектирования¶
Обещать exactly-once по одному компоненту; не хранить stable identity/version; путать ACK, visible state и восстановимость; не учитывать replay/retention horizon. Таблица отказов задаёт обязательные сценарии дальнейшего тестирования.
Вопросы на собеседовании¶
Где заканчивается транзакционная гарантия? На явно указанной local/engine boundary. Все последующие projections требуют собственного delivery/retry/version contract и контроля полноты.
Практические упражнения¶
Проверьте duplicate retry до/после окна, deny без продления TTL, expired snapshot, reorder versions и state loss. В полноценной среде добавьте checkpoint recovery, lost ACK, clock step и Redis promotion; зафиксируйте полноту feature windows до открытия трафика.
Дополнительные источники¶
Общий отчёт проверок (архив рабочего проекта). Ни статическая проверка, ни model test не подтверждают production reliability.