我正在读取一个简单的JSON字符串作为输入,并基于两个字段A
和B
输入流的键。但是KeyBy会为B
的不同值,但为A
和B
的特定组合生成相同的密钥流。
输入:
{
"A": "352580084349898",
"B": "1546559127",
"C": "A"
}
这是我的Flink代码的核心逻辑:
DataStream<GenericDataObject> genericDataObjectDataStream = inputStream
.map(new MapFunction<String, GenericDataObject>() {
@Override
public GenericDataObject map(String s) throws Exception {
JSONObject jsonObject = new JSONObject(s);
GenericDataObject genericDataObject = new GenericDataObject();
genericDataObject.setA(jsonObject.getString("A"));
genericDataObject.setB(jsonObject.getString("B"));
genericDataObject.setC(jsonObject.getString("C"));
return genericDataObject;
}
});
DataStream<GenericDataObject> testStream = genericDataObjectDataStream
.keyBy("A", "B")
.map(new MapFunction<GenericDataObject, GenericDataObject>() {
@Override
public GenericDataObject map(GenericDataObject genericDataObject) throws Exception {
return genericDataObject;
}
});
testStream.print();
GenericDataObject是具有三个字段A
,B
和C
的POJO。
这是字段B
的不同值的控制台输出。
5> GenericDataObject{A='352580084349898', B='1546559224', C='A'}
5> GenericDataObject{A='352580084349898', B='1546559127', C='A'}
4> GenericDataObject{A='352580084349898', B='1546559234', C='A'}
3> GenericDataObject{A='352580084349898', B='1546559254', C='A'}
注意第1行和第2行。即使它们具有不同的B值,也将它们置于相同的键控流(5)中。我肯定在这里做错了什么,有人可以指出正确的方向吗?
答案 0 :(得分:4)
首先,您没有做错任何事。
为什么它们在同一个子任务中?
假定您有数千个密钥,并且Apache Flink不可能为每个密钥创建数千个线程。因此,必须有另一种机制来确保一组密钥在一个线程中被单独处理。
因此,在Apache Flink中,每个子任务都有自己的密钥组,具有相同密钥组索引的不同密钥将在同一子任务中处理。子任务通常会处理几个具有单独键控状态的键,以保持不同键的状态分开。
keyBy并不意味着将不同的键分配给不同的子任务(或分区),但是具有相同键的所有记录都将分配给相同的子任务。因此,您只能通过对KeySelector实例进行编程来确定不同的密钥是否在同一组中。
有关更多详细信息,您可以在Apache Flink的官方网站上查看此文章。