簡體   English   中英

在重新連接時始終從 Kafka 檢索最新消息

[英]Retrieve always latest messages from Kafka on reconnection

我正在編寫一段代碼,需要每隔幾毫秒從 Kafka 讀取數百條消息。 我正在使用 C++ 和 librdkafka。 當我的程序停止然后重新啟動時,它不需要恢復自停止以來所有丟失的消息,而是需要始終從發送的最新消息中讀取。

據我所知,我可以通過使用enable.auto.commitauto.offset.reset來管理消費者偏移量。 但是,后者僅在沒有提交的偏移量時才有用,而前者讓我自己管理要存儲的偏移量。

使用這兩個值,我發現如果我將enable.auto.commit設置為false ,而不提交任何偏移量,並將auto.offset.resetlatest它似乎總是檢索最新消息; 但是這個解決方案有多干凈?

我擔心的是,如果在兩個消費者輪詢之間發送了 2 條消息,而我的消費者只接收最新的消息,或者如果沒有發送的消息,它會持續讀取相同的消息。 兩者都是不受歡迎的行為。

另一個想法是清除消費者組偏移或向前搜索,但 librdkafka 中的seek方法似乎無法按需要工作,我找不到管理消費者組的方法。

如何使用 librdkafka 始終閱讀來自 Kafka 的最新消息?

最后我通過管理自己的重新平衡回調來解決。 當新的消費者加入或離開組時,將始終執行此回調。

rebalance 回調負責根據兩個事件更新 librdkafka 的分配集:RdKafka::ERR__ASSIGN_PARTITIONS 和 RdKafka::ERR__REVOKE_PARTITIONS。

因此,在重新平衡回調中,我迭代了TopicPartition s,以便使用最新的偏移量將它們分配給消費者。 代碼片段是這樣的:

class SeekEndRebalanceCb : public RdKafka::RebalanceCb {
  public:
  void rebalance_cb (RdKafka::KafkaConsumer *consumer, RdKafka::ErrorCode err, std::vector<RdKafka::TopicPartition*> &partitions) {
    if (err == RdKafka::ERR__ASSIGN_PARTITIONS) {
      for (auto partition = partitions.begin(); partition != partitions.end(); partition++) {
        (*partition)->set_offset(RdKafka::Topic::OFFSET_END);
      }
      consumer->assign(partitions);
    } else if (err == RdKafka::ERR__REVOKE_PARTITIONS) {
      consumer->unassign();
    } else {
      std::cerr << "Rebalancing error: " << RdKafka::err2str(err) << std::endl;
    }
  }
};

為了使用該回調,我將其設置為消費者。

SeekEndRebalanceCb ex_rb_cb;
if (consumer->set("rebalance_cb", &ex_rb_cb, errstr) != RdKafka::Conf::CONF_OK) {
  std::cerr << errstr << std::endl;
  return false;
}

consumer->assign(partitions) 應在循環結束后調用

class SeekEndRebalanceCb : public RdKafka::RebalanceCb {
  public:
  void rebalance_cb (RdKafka::KafkaConsumer *consumer, RdKafka::ErrorCode err, std::vector<RdKafka::TopicPartition*> &partitions) {
    if (err == RdKafka::ERR__ASSIGN_PARTITIONS) {
       for (auto partition = partitions.begin(); partition != partitions.end(); partition++) 
           (*partition)->set_offset(RdKafka::Topic::OFFSET_END);
       consumer->assign(partitions);
    } else if (err == RdKafka::ERR__REVOKE_PARTITIONS) {
      consumer->unassign();
    } else {
      std::cerr << "Rebalancing error: " << RdKafka::err2str(err) << std::endl;
    }
  }
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM