メッセージパーティションとDefaultPartitionerソースコード解析を指定するにはカフカのカスタムポリシールール
I.概要
カフカDefaultPartitionerデフォルト、デフォルトの設定では、ProducerConfig特定のクラスのデフォルトのパーティションポリシールールとしてクラスである(下記参照)
二.DefaultPartitioner.classソースコード解析
1.図のクラス関係
2.ソース解析
public class DefaultPartitioner implements Partitioner {
//缓存map key->topic value->RandomNumber 随机数
private final ConcurrentMap<String, AtomicInteger> topicCounterMap = new ConcurrentHashMap<>();
//实现Configurable接口里configure方法,
public void configure(Map<String, ?> configs) {}
//策略核心方法
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
//根据topic获取对应的partition
List<PartitionInfo> partitions = cluster.partitionsForTopic(topic);
int numPartitions = partitions.size();
//如果key是null的话
if (keyBytes == null) {
int nextValue = nextValue(topic);
//获取可用的分区数量
List<PartitionInfo> availablePartitions = cluster.availablePartitionsForTopic(topic);
//如果存在可用的分区
if (availablePartitions.size() > 0) {
//消息随机分布到topic的可用partition中
int part = Utils.toPositive(nextValue) % availablePartitions.size();
return availablePartitions.get(part).partition();
} else {
//不存在可用分区 随机分配一个不可用的partition中
return Utils.toPositive(nextValue) % numPartitions;
}
} else {
//使用自己的 hash 算法对 key 取 hash 值,使用 hash 值与 partition 数量取模,从而确定发送到哪个分区。
return Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions;
}
}
private int nextValue(String topic) {
//获取topic 获取对应的随机数
AtomicInteger counter = topicCounterMap.get(topic);
if (null == counter) {
//获取一个随机值
counter = new AtomicInteger(ThreadLocalRandom.current().nextInt());
//缓存到topicCounterMap中
AtomicInteger currentCounter = topicCounterMap.putIfAbsent(topic, counter);
if (currentCounter != null) {
counter = currentCounter;
}
}
//获取 并且实现自增,最终效果是实现轮训插入partition
return counter.getAndIncrement();
}
public void close() {}
}
III。カスタムパーティション
SelfPartitionerのカスタムクラス、および実装インタフェースパーティショナ、書き換えパーティションと近い方法
public class SelfPartitioner implements Partitioner {
@Override
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
//TODO 自定义数据分区策略
return 0;
}
@Override
public void close() {
}
@Override
public void configure(Map<String, ?> configs) {
}
}
IV。生産用カスタムパーティション
初期化時間プロデューサーに、コンフィギュレーション項目パーティショナ対応する指定
props.put("partitioner.class", "org.jake.partitioner.selfPartitioner");