flink int序列化

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);
}

 

Flink序列化机制是将数据从Java对象转换为字节序列的过程,以便在网络上传输或存储到磁盘中。Flink使用Kryo作为默认的序列化器,Kryo是一个快速高效的Java序列化框架,可以将Java对象序列化为字节数组,也可以将字节数组反序列化为Java对象。在Flink中,序列化器是根据数据类型来选择的,不同的数据类型有不同的序列化器。例如,对于Tuple、Pojo和CaseClass等复合类型,它们的序列化器是复合的,会将内嵌类型的序列化委托给对应类型的序列化器。在序列化操作时,会委托相应具体序列化序列化器进行相应的序列化操作。Flink还提供了WritableSerializer和AvroSerializer等其他类型的序列化器,用户可以根据需要选择不同的序列化器。 示例代码如下: ```java // 定义一个POJO类 public class Person implements Serializable { private String name; private int age; public Person() {} public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } // 使用Kryo序列化器将Person对象序列化为字节数组 Person person = new Person("张三", 20); KryoSerializer<Person> serializer = new KryoSerializer<>(Person.class, new ExecutionConfig()); byte[] bytes = serializer.serialize(person); // 使用Kryo序列化器将字节数组反序列化为Person对象 Person person2 = serializer.deserialize(bytes); System.out.println(person2.getName() + " " + person2.getAge()); // 输出:张三 20 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值