Flink中int的存储并不是直接通过int来存储,而是通过IntValue来存储,这样在内存中只需要存储4个字节大小的数据就可以保证单个int数据的存储。
private int value;
在IntValue中用value字段来保存所需要的int字段。
在IntValue中值得一提的是copyNormaliedKey()方法。
@Override
public void copyNormalizedKey(MemorySegment target, int offset, int len) {
// take out value and add the integer min value. This gets an offset
// representation when interpreted as an unsigned integer (as is the case
// with normalized keys). write this value as big endian to ensure the
// most significant byte comes first.
if (len == 4) {
target.putIntBigEndian(offset, value - Integer.MIN_VALUE);
}
else if (len <= 0) {
}
else if (len < 4) {
int value = this.value - Integer.MIN_VALUE;
for (int i = 0; len > 0; len--, i++) {
target.put(offset + i, (byte) ((value >>> ((3-i)<<3)) & 0xff));
}
}
else {
target.putIntBigEndian(offset, value - Integer.MIN_VALUE);
for (int i = 4; i < len; i++) {
target.put(offset + i, (byte) 0);
}
}
}
这个方法会将int值按照接口NormalizableKey的规定生成制定长度的规范键来存储到内存中以便比较。其中,如果给定的长度大于int的大小4字节,将会填充0到字节大小对齐。如果给定的长度小于原本int所需要的四字节,那么只会存储前几个字节,失去低位比较的精度。
IntValue通过write()方法将int数据存储到内存中。
@Override
public void write(DataOutputView out) throws IOException {
out.writeInt(this.value);
}
最终还是调用的是DataOutputView的writeInt()方法,DataOutputView是内存在MemorySegment基础之上的进一步抽象。
以AbstractpagedInputView为例子,AbstractpagedInputView是所有分页内存实现类需要继承的抽象类。
@Override
public void writeInt(int v) throws IOException {
if (this.positionInSegment < this.segmentSize - 3) {
this.currentSegment.putIntBigEndian(this.positionInSegment, v);
this.positionInSegment += 4;
}
else if (this.positionInSegment == this.segmentSize) {
advance();
writeInt(v);
}
else {
writeByte(v >> 24);
writeByte(v >> 16);
writeByte(v >> 8);
writeByte(v);
}
}
如果当前AbstractpagedInputView所对应的MemerySegment剩余大小大于4字节,那么将会直接保存到当前MemerySegment的byte数组当中,同时代表当前位置的偏移量移动4个字节大小的位置。如果当前大小正好耗完,那么将会通过advance()方法得到一个新的memorySegmet来进行存储。如果剩余大小不为0也小于4字节,那么将会逐字节进行存储。
结合上者,看到IntValueSerializer的serialize()方法,关于int值的序列化过程也清楚了。
@Override
public void serialize(IntValue record, DataOutputView target) throws IOException {
record.write(target);
}