This document discusses different approaches for achieving exactly-once semantics when streaming data from Kafka using Spark Streaming. It presents idempotent and transactional approaches. The idempotent approach works for transformations that have a natural unique key, while the transactional approach works for any transformation by committing offsets and results together in a transaction. It also compares receiver-based and direct streaming, noting the pros and cons of each, and how to store offsets to enable exactly-once processing when using the direct approach.