if (currentPartitionId > 0 && (currentPartitionId % brokerArray.length == 0))
nextReplicaShift += 1
val firstReplicaIndex = (currentPartitionId + startIndex) % brokerArray.length
val replicaBuffer = mutable.ArrayBuffer(brokerArray(firstReplicaIndex))
for (j <- 0 until replicationFactor - 1)
replicaBuffer += brokerArray(replicaIndex(firstReplicaIndex, nextReplicaShift, j, brokerArray.length))
ret.put(currentPartitionId, replicaBuffer)
currentPartitionId += 1
}
ret
}
//主要的计算间隔数的方法
private def replicaIndex(firstReplicaIndex: Int, secondReplicaShift: Int, replicaIndex: Int, nBrokers: Int): Int = {
val shift = 1 + (secondReplicaShift + replicaIndex) % (nBrokers - 1)
(firstReplicaIndex + shift) % nBrokers
}
-
从 broker.list 随机选择一个 Broker,使用 round-robin 算法分配每个 partition 的第一个副本;
-
对于这个 partition 的其他副本,逐渐增加 Broker.id 来选择 replica 的分配。
-
对于副本分配来说,每经历一次Broker的遍历,则第一个副本跟后面的副本直接的间隔+1;
从代码和描述来看,可能理解不是很简单,但是下面的图我相信会让你非常快速的理解;
我们稍微在这段代码里面节点日志
然后写段单元测试,执行一下,看看分配过程
Broker列表{0,1,2,3,4} 分区数 10 副本数3 起始随机BrokerId=0; 起始随机nextReplicaShift=0
@Test
def testReplicaAssignment2(): Unit = {
val brokerMetadatas = (0 to 4).map(new BrokerMetadata(_, None))
AdminUtils.assignReplicasToBrokers(brokerMetadatas, 10, 3, 0)
}
输出:
起始随机startIndex:0;起始随机nextReplicaShift:0
(p-0,ArrayBuffer(0, 1, 2))
(p-1,ArrayBuffer(1, 2, 3))
(p-2,ArrayBuffer(2, 3, 4))
(p-3,ArrayBuffer(3, 4, 0))
(p-4,ArrayBuffer(4, 0, 1))
变更nextReplicaShift:1
(p-5,ArrayBuffer(0, 2, 3))
(p-6,ArrayBuffer(1, 3, 4))
(p-7,ArrayBuffer(2, 4, 0))
(p-8,ArrayBuf