[英]Retrieve always latest messages from Kafka on reconnection
我正在編寫一段代碼,需要每隔幾毫秒從 Kafka 讀取數百條消息。 我正在使用 C++ 和 librdkafka。 當我的程序停止然后重新啟動時,它不需要恢復自停止以來所有丟失的消息,而是需要始終從發送的最新消息中讀取。
據我所知,我可以通過使用enable.auto.commit
和auto.offset.reset
來管理消費者偏移量。 但是,后者僅在沒有提交的偏移量時才有用,而前者讓我自己管理要存儲的偏移量。
使用這兩個值,我發現如果我將enable.auto.commit
設置為false
,而不提交任何偏移量,並將auto.offset.reset
為latest
它似乎總是檢索最新消息; 但是這個解決方案有多干凈?
我擔心的是,如果在兩個消費者輪詢之間發送了 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.