Kafka集群更新元数据 - waitOnMetadata()
通过比较版本号的方式,控制数据一致性。类似乐观锁的方式。 Sender线程在更新成功元数据之前,会一直阻塞主线程。
private long waitOnMetadata(String topic, logn maxWaitMs) throws InterruptedException {
// metadata里没有指定topic的键值,就添加这个键值。
if (!this.metadata.containsTopic(topic))
metadata.add(topic);
// metadata里的指定topic不为空,表示元数据修改完成
if (metadata.fetch().partitionsForTopic(topic) != null)
return 0;
// 程序的起始执行时间
long begin = time.milliseconds();
// 剩余时间(开始为最大等待时间)
long remainingWaitMs = maxWaitMs;
// 当元数据没有修改完成的时候
while (metadata.fetch().partitionsForTopic(topic) == null) {
// 获取当前版本号
int version = metadata.requestUpdate();
// 唤醒sender线程,由sender线程执行元数据修改
sender.wakeup();
// 更新元数据
metadata.awaitUpdate(version, remainingWaitMs);
// 程序的执行时间
long elapsed = time.milliseconds() - begin;
if (eplased >= maxWaitMs)
throw new TimeoutException(..);
// 权限的验证
if (metadata.fetch().unauthorizedTopics().contains(topic))
throw new TopicAuthorizationException(topic);
remainingWaitMs = maxWaitMs - elapsed;
}
// 最终的程序执行时间
return time.milliseconds() - begin;
}
public synchronized void awaitUpdate(final int lastVersion, final long maxWaitMs) {
....
long begin = System.currentTimeMillis();
long remainingWaitMs = maxWaitMs;
// 记录的版本号小于等于最新版本号
while (this.version <= lastVersion) {
if (remainingWaitMs != 0)
// 阻塞主线程
wait(remainingWaitMs);
// 程序的执行时间
long elapsed = System.currentTimeMillis - begin;
// 如果程序的执行时间大于等于最大等待时间
if (elapsed >= maxWaitMs)
throw new TimeOutException(..);
// 剩余时间等于最大等待时间减去程序执行时间
remainingWaitMs = maxWaitMs - elapsed;
}
}