With Kafka it "just" keeps appending to a dumb (but huge) circular buffer. But you can have multiple consumers read off this buffer and can start any point. Downside is customers have to maintain their own offsets (in some storage) but there is now a big decoupling between producer and consumer. This contributes a large part to high throughput too (and consumers can go at their own pace -ofcourse if they are too slow they can fall off the log).
Minor correction: you can maintain the offsets yourself if you want, but usually it's not necessary because Kafka can do it for you.
The abstraction Kafka provides is that for each consumer group and for each (topic, partition) tuple, your consumer object that is guaranteed not to receive messages before the last offset at which you called commit(). Internally, the committed offsets are stored in a special Kafka topic of their own.
Kafka is a stream, RabbitMQ is a queue. Without getting into the details, RabbitMQ is designed to add things to a stack and pop them off when consumed. Kafka is designed to stream everything to a continuous log and anywhere can tune in when appropriate.
RabbitMQ messages are supposed to be processed/consumed/acked only once. Your app most probably won't ever get two exactly the same messages, unless you misconfigured/misued RabbitMQ. It's good for classic message processing - "used clicked something, run the job of informing subscribers that new post has been created" (because you can't send 1000 messages from a web worker thread).
I wouldn't use Kafka for a job queue, and wouldn't use RabbitMQ for streaming data when ordering would be important.
https://eranstiller.com/rabbitmq-vs-kafka-an-architects-dile...