2.Flink序列化机制

概述

  在两个进程进行远程通信时,它们需要将各种类型的数据以二进制序列的形式在网络上传输,数据发送方需要将对象转换为字节序列,进行序列化,而接收方则将字节序列恢复为各种对象,进行反序列化。对象的序列化有两个主要用途:一是将对象的字节序列永久保存到硬盘上,通常存放在文件中;二是在网络上传输对象的字节序列。序列化的好处包括减少数据在内存和硬盘中的占用空间,减少网络传输开销,精确推算内存使用情况,降低垃圾回收的频率。

注意

  Flink序列化机制负责在节点之间传输数据时对数据对象进行序列化和反序列化,确保数据的正确性和一致性。Flink提供了多种序列化器,包括Kryo、Avro和Java序列化器等,大多数情况下,用户不用担心flink的序列化框架,Flink会通过TypeInfomation在数据处理之前推断数据类型,进而使用对应的序列化器,例如:针对标准类型(int,double,long,string)直接由Flink自带的序列化器处理,其他类型默认会交给Kryo处理。但是对于Kryo仍然无法处理的类型,可以采取以下两种解决方案:

强制使用Avro替代Kryo序列化

//设置flink序列化方式为avro
env.getConfig().enableForceAvro();

自定义注册Kryo序列化

//注册kryo 自定义序列化器
env.getConfig().registerTypeWithKryoSerializer(Class<?> type, Class<? extends Serializer> serializerClass)

实践

自定义pojo

public class SerializerTest {
    public static void main(String[] args) throws Exception {
        //准备环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        // Flink会自动识别数据类型,当符合要求时,会优先使用其定制的序列化框架,否则,将默认使用Kryo完成序列化
        // 关闭使用 kryo
        env.getConfig().disableGenericTypes();
        //source ,socket:1,zs,18
        DataStreamSource<String> ds = env.socketTextStream("localhost", 9999);

        ds.map(new MapFunction<String, Student>() {
            @Override
            public Student map(String s) throws Exception {
                String[] arr = s.split(",");
                return new Student(Integer.valueOf(arr[0]), arr[1], Integer.valueOf(arr[2]));
            }
        }).print();
        env.execute();
    }
}
public class Student {
    private Integer id;
    private String name;
    private Integer age;

    public Student() {
    }

    public Student(Integer id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

在这里插入图片描述
没有序例化时,也是可以正常使用的。

自定义pojo kryo序例化

public class SerializerTestT {
    public static void main(String[] args) throws Exception {
        //准备环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.getConfig().registerTypeWithKryoSerializer(Student.class, StudentSerializer.class);

        //source ,socket:1,zs,18
        DataStreamSource<String> ds = env.socketTextStream("localhost", 9999);

        ds.map(new MapFunction<String, Student>() {
            @Override
            public Student map(String s) throws Exception {
                String[] arr = s.split(",");
                return new Student(Integer.valueOf(arr[0]), arr[1], Integer.valueOf(arr[2]));
            }
        }).print();
        env.execute();
    }
}
/**
 * 顺序不要变
 */
public class StudentSerializer extends Serializer {

    @Override
    public void write(Kryo kryo, Output output, Object o) {
        Student student = (Student) o;
        output.writeInt(student.getId());
        output.writeString(student.getName());
        output.writeInt(student.getAge());

    }

    @Override
    public Object read(Kryo kryo, Input input, Class aClass) {
        Student student = new Student();
        student.setId(input.readInt());
        student.setName(input.readString());
        student.setAge(input.readInt());
        return student;
    }
}

结束

Flink序列化机制

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
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
发出的红包

打赏作者

流月up

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值