直入正题,flink写入kafka根据某个数据中的字段做分区发送到kafka的指定分区,如果你在sink中每次要手动写producer,那么你可以略过此文章
接着上篇文章flink写入kafka之默认序列化类和默认分区器
- 直接上代码
/*自定义分区*/
@SuppressWarnings("unchecked")
FlinkKafkaProducer010<String> flinkProducer = new FlinkKafkaProducer010<String>(
"topic名字",
//自定义元数据
new MySchema(),
//kafka producer的属性
pro,
//自定义分区器
new MyPartitioner());
flinkDataStream.addSink(flinkProducer).setParallelism(2);
- 我们自己定义的元数据类
public static class MySchema implements KeyedSerializationSchema {
//element: 具体数据
/**
* 要发送的key
*
* @param element 原数据
* @return key.getBytes
*/
@Override
public byte[] serializeKey(Object element) {
//这里可以随便取你想要的key,然后下面分区器就根据这个key去决定发送到kafka哪个分区中,
//element就是flink流中的真实数据,取出key后要转成字节数组
return element.toString().split("\u0000")[0].getBytes();
}
/**
* 要发送的value
*
* @param element 原数据
* @return value.getBytes
*/
@Override
public byte[] serializeValue(Object element) {
//要序列化的value,这里一般就原封不动的转成字节数组就行了
return element.toString().getBytes();
}
@Override
public String getTargetTopic(Object element) {
//这里返回要发送的topic名字,没什么用,可以不做处理
return null;
}
}
- 我们自己定义的分区器
public static class MyPartitioner extends FlinkKafkaPartitioner {
/**
* @param record 正常的记录
* @param key KeyedSerializationSchema中配置的key
* @param value KeyedSerializationSchema中配置的value
* @param targetTopic targetTopic
* @param partitions partition列表[0, 1, 2, 3, 4]
* @return partition
*/
@Override
public int partition(Object record, byte[] key, byte[] value, String targetTopic, int[] partitions) {
//这里接收到的key是上面MySchema()中序列化后的key,需要转成string,然后取key的hash值`%`上kafka分区数量
return Math.abs(new String(key).hashCode() % partitions.length);
}
}
这样flink发送到kafka的数据就不是随便发的了,是根据你定义的key发送的