Kafka用于微服务的事件采购

时间:2018-10-05 13:19:11

标签: apache-kafka kafka-consumer-api kafka-producer-api event-sourcing recovery

我有几个使用kafka数据的微服务。他们消费并产生数据给经纪人。

那些微服务仅具有易失性存储(hazelcast)。当存储丢失时,我需要基于kafka中的主数据对其进行重建。

我的naiv实现只是再次使用这些数据,但是随后我向代理生成了一些旧数据。这再次触发了其他微服务,这似乎是一个坏主意。

是否有处理此用例的标准方法?对我来说,这似乎是一个非常普遍的问题,还是我做错了什么?

2 个答案:

答案 0 :(得分:0)

有人问过before

将Kafka用作事件存储并不重要,因为问题在于微服务会重新发送事件。

答案 1 :(得分:0)

花了几天后,我想到了以下解决方案。

关键思想是以两种模式进行同步,即恢复和正常

  • 在恢复模式下,我仅消耗数据,但不产生任何数据。
  • 在正常模式下,我消耗并产生数据。

在Kafka中,我使用了两个属于不同消费者组的侦听器来实现此目的。在启动时,所有侦听器都停止,我决定启用某种侦听器。一旦所有恢复侦听器的偏移量达到正常侦听器的水印,我就停止恢复列表器并启动正常侦听器。

在我的代码的相关部分之下:

public void startListeners() {
    log.debug("get partitions from application");
    final List<KafkaPartitionStateKey> partitions = getPartitions();

    log.debug("load partition state from hazelcast");
    final Map<KafkaPartitionStateKey, KafkaPartitionState> kafkaPartitionStates = kafkaPartitionStateService.loadKafkaPartitionStateMap();

    log.debug("check if in sync");
    if (areAllPartitionsReady(partitions, kafkaPartitionStates)) {
        log.info("all partitions ready, not need to start recovery");
        this.messageListenerContainers.forEach(this::startContainer);
        return;
    }

    log.debug("load consumer group offsets from kafka");
    consumerGroupOffsets = getConsumerGroupOffsets();

    log.debug("create missing partition states");
    final List<KafkaPartitionState> updatedPartitionStates = getOrCreatePartitionStates(partitions, kafkaPartitionStates, consumerGroupOffsets);

    log.debug("check if all partitions are ready");
    if (getNumberOfNotReadyPartitions(updatedPartitionStates) == 0) {
        log.info("all partitions ready, no need to start recovery");
        this.messageListenerContainers.forEach(this::startContainer);
        return;
    }

    log.info("----- STARTING RECOVERY -----");
    this.recoveryListenerContainers.forEach(this::startContainer);
}

我希望这对某人有用...