Flink序列化问题

产生原因

引用了某类的成员变量或函数,并且相应的类没有做好序列化处理,引用了某类的成员函数或变量,则需对相应的类做好序列化处理

解决办法

方法1:声明为@transent
在map()算子中继承了的RichMapFunction的类,其中的由于对象都需要序列化,但是对于不能够实现的序列化接口的对象比如数据库连接对象SqlConnection(mySQL、Postgresql等)和GeomentyFactory对象等,自身不可以序列化的对象,则声明为@transent
再分为两点:
(1)对象在需要在map()中不停调用的时候,这时候需要在open()中序列化,这个跟设置的并发线程数有关系。比如设置并发parallel=10,则该对象被初始化10次,生成是个对象,分别被10个线程调用;
(2)假如对象只需要在在后期实用一次,比如数据库连接SqlConnection在加载一次缓存(一般是不变的缓存),则最好是放在该类的构造函数中初始化,执行1次;

方法2:声明为静态
对于像数据库连接对象SqlConnection等不可以序列化的对象,由于该对象是长连接不可变对象,可以声明为静态对象(类对象),JVM会将该对象放入永久代Perminate 中,实现Flink多线程共享并发访问;
同理,所有不可变的小对象(不可变缓存(如hashMap)是指小的缓存对象)都可以声明为静态对象,因此,此时不用对该对象声明为@transent而表明不可以序列化;

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、付费专栏及课程。

余额充值