We have data in Kafka which we need to export to multiple destinations. Each message key is to be exported to one destination.
A destination can be a REST endpoint, a file, a database etc.
Each exporter can have its own speed or rate limits and one exporter should not slow down the other.
In Kafka, the parallelism is dependent on the number of partitions, rather on the no. of messages.
Approach #1
We decided to use Akka where we read each message from the Kafka topic and tell
to the exporter actors each of which will export to their respective destination like REST, file, database etc.
Problem: At-most once semantics only. The problem here is that, we have to commit the messages in Kafka. When we tell
to an actor, we do not know, whether that actor has processed that message or not. It may still lie in the mailbox and we may commit that message. These committed messages are not read again after process restart.
while(true) {
consumer.poll().forEach( record -> {
getExporter(record.key()).tell(record, ActorRef.noSender()));
});
consumer.commitAsync();
}
Approach #2
Read each message, store it in a persistent file, export it and remove it from the persistent file after export.
We need a persistent actor for this, for whom we need to tell
to. So, we may use ask
for this and wait till the actor puts it into the map and then tell it to the exporter.
Are there any better ways of doing this? Are there any reference architectures?