策略一: 如果发送消息的时候,没有指定key, 轮询达到负载均衡
//策略二:这个地方就是指定了key, hash取模,相同的key打到同一个分区上
int partition = partition(record, serializedKey, serializedValue, cluster);
->
return partition != null ?
partition :
//使用分区器进行选择合适的分区
partitioner.partition(
record.topic(), record.key(), serializedKey, record.value(), serializedValue, cluster);
==================================================================================================================
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
//首先获取到我们要发送消息的对应的topic的分区的信息
List<PartitionInfo> partitions = cluster.partitionsForTopic(topic);
//计算出来分区的总的个数
int numPartitions = partitions.size();
/**
* producer 发送数据的时候:
* message
*
* key,message
* message
*
*/
//策略一: 如果发送消息的时候,没有指定key
if (keyBytes == null) {
//这儿有一个计数器
//每次执行都会加一
//10
int nextValue = counter.getAndIncrement();
//获取可用的分区数
List<PartitionInfo> availablePartitions = cluster.availablePartitionsForTopic(topic);
if (availablePartitions.size() > 0) {
//计算我们要发送到哪个分区上。
//一个数如果对10进行取模, 0-9之间
//11 % 9
//12 % 9
//13 % 9
//实现一个轮训的效果,能达到负载均衡。
int part = Utils.toPositive(nextValue) % availablePartitions.size();
//根据这个值分配分区好。
return availablePartitions.get(part).partition();
} else {
// no partitions are available, give a non-available partition
return Utils.toPositive(nextValue) % numPartitions;
}
} else {
//策略二:这个地方就是指定了key
// hash the keyBytes to choose a partition
//直接对key取一个hash值 % 分区的总数取模
//如果是同一个key,计算出来的分区肯定是同一个分区。
//如果我们想要让消息能发送到同一个分区上面,那么我们就
//必须指定key. 这一点非常重要
//希望大家一定一定要知道。
return Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions;
}
}