Requirements and constraints:- Exactly-once semantics for feature computations- Low-latency (<50–200ms) reads for inference- Support event-time aggregations (windows), late data, and incremental updates- Scalable, fault-tolerant, observableHigh-level approach:- Use Flink (recommended) or Kafka Streams for stateful stream processing; Kafka as durable ingestion and changelog.- Compute features in streaming jobs and publish materialized feature values to an online store (Redis/KeyDB/Cassandra) for low-latency reads; keep feature change log in Kafka for recovery and audit.State management & exactly-once:- Flink with RocksDB state backend to hold large keyed state (per-entity aggregates). RocksDB provides fast local disk-backed state.- Enable Flink checkpointing to durable storage (S3/GCS) with a reasonable interval (e.g., 5–30s) and configure timeout/retention.- Use Flink’s two-phase commit sink or Kafka transactions to write to both Kafka changelog topics and the online store with exactly-once semantics: - Preferred pattern: write feature updates to a Kafka “feature-changelog” topic within Flink’s checkpointed two-phase commit; have a separate idempotent consumer that materializes to Redis, or use Flink’s transactional sink to atomically write to Kafka and a staging buffer then commit on checkpoint.- Configure checkpointing and Kafka producer/consumer transactional IDs to avoid duplicates. Ensure operator state is checkpointed and restored deterministically.Windowing and aggregations:- Use event-time processing with watermarks to compute windowed features (tumbling, sliding, session): - Example: 1h sliding window with 5min slide for rolling averages.- Implement user-defined process functions for complex features (e.g., percentile via digest sketches).- Handle late/out-of-order events via allowed lateness; decide whether to update materialized features on late arrivals (retract/update patterns).- For incremental aggregates use incremental algorithms: count/sum/avg via incremental state; quantiles via t-digest or KLL sketches; heavy hitters via CMSketch.Exposing features for low-latency inference:- Materialize features to an online key-value store (Redis) keyed by entity id. Writes come from the feature-changelog topic (consumer that applies updates idempotently).- Ensure read-after-write consistency: pipeline writes a version or timestamp with each feature; inference can either wait for checkpoint-confirmed updates or read latest value and accept eventual consistency if tolerable.- Provide a service layer (gRPC/HTTP) that: - Fetches features from Redis with sub-ms lookups - Falls back to a “feature fetch” from a cold store (Cassandra) if missing - Supports bulk multi-entity fetches and caching- For ultra-low-latency model serving, colocate model server and Redis in same AZ; use connection pooling and pipelining.Operational considerations:- Monitoring: track checkpoint latency/success, Kafka offsets, state size, RocksDB compaction metrics, sink latencies, feature drift.- Testing: end-to-end reproducible tests using recorded input topics and deterministic state restore; fuzz with out-of-order/late events.- Schema/versioning: evolve feature schemas via Avro/Protobuf with compatibility; include metadata (timestamp, version, TTL).- TTL & compaction: set TTL for online store and retention/compaction policy for changelog topics.Example snippet (Flink pseudo):java
// Key by entity, event-time with watermarks
stream
.assignTimestampsAndWatermarks(...)
.keyBy(event -> event.id)
.window(SlidingEventTimeWindows.of(Time.hours(1), Time.minutes(5)))
.aggregate(new IncrementalAgg(), new WindowProcess())
.map(feature -> toKafkaProducerRecord(feature)) // transactional sink
.sink(new FlinkKafkaProducer<>(... , flinkKafkaSemantic.EXACTLY_ONCE));
Trade-offs:- Exactly-once to external DB is hard; best practice is exactly-once to Kafka changelog and idempotent/transactional materializer to online store.- Shorter checkpoint intervals reduce data loss but increase overhead; tune with SLOs.This design gives robust exactly-once feature computation, supports complex windowed aggregates, and serves features with low latency suitable for production inference.