Flink Table API & SQL 自定义Redis Sink 代码实现

在自定义source&sink这一块官方给的说明并不是很多,需要去看源代码熟悉,自己实现一个redis sink主要需要实现StreamTableSinkFactory,RichSinkFunction和AppendStreamTableSink/RetractStreamTableSink/UpsertStreamTableSink,代码逻辑依赖主要如下

1.定义TableFactory

定义一个TableSinkFactory需要实现以下一个或者多个接口,在这里只实现StreamTableSinkFactory

  • BatchTableSourceFactory: Creates a batch table source.
  • BatchTableSinkFactory: Creates a batch table sink.
  • StreamTableSourceFactory: Creates a stream table source.
  • StreamTableSinkFactory: Creates a stream table sink.
  • DeserializationSchemaFactory: Creates a deserialization schema format.
  • SerializationSchemaFactory: Creates a serialization schema forma

createStreamTableSink():在这里能够拿到ddl的with参数,我们通过getValidatedProperties进行合法性校验,再将参数构建为一个RedisOptions供后续方法使用,tableSchema主要包含ddl语句字段信息,最后返回实例化的RedisTableSink
requiredContext():指定已为此工厂实现的上下文。该框架保证仅在满足指定的属性和值集的情况下才与此工厂匹配。典型的属性可能是connector.type,format.type或update-mode。 为将来的向后兼容情况保留了诸如connect.property-version和format.property-version之类的属性键。
supportedProperties():此工厂可以处理的属性键的列表。此方法将用于验证。如果传递了该工厂无法处理的属性,则将引发异常。该列表不得包含上下文指定的键。
getValidatedProperties():构建DescriptorProperties并作合法性校验

2.定义TableSink

定义一个TableSink可以实现BatchTableSink、RetractStreamTableSink、UpsertStreamTableSink或者AppendStreamTableSink,redis的数据写入,我们按照来一条写一条的思路来实现,不涉及到数据的删除,所以只需要继承AppendStreamTableSink

consumeDataStream():在这里能够拿到数据流,在addSink的时候将实例化的RedisSinkFunction写入方法传进去即可
emitDataStream():已经废弃
configure():拿到的是sql返回字段和类型,在这里我们和tableSchema做一致性校验,必须完全对应才能通过
getConsumedDataType():返回Consumed数据类型
getTableSchema():返回tableSchema信息

3.定义RedisSinkFunction

定义RedisSinkFunction需要继承RichSinkFunction,如果需要在Checkpoint时候做一些事情还可以实现CheckpointedFunction

open():可以在这里构建jedis方法
close():在这里执行销毁或者关闭方法
invoke():数据写入的执行方法,我们这里根据ddl的connector.data.type类型来确定调用的方法,目前先实现了string,set,list,map,sortedset五种
snapshotState():如果是mysql或者hbase那种定时/定量写入方式,可以在这里调用写入方法

4.创建java spi发现目录和文件

在resources目录下创建META-INF/services文件夹,创建一个名为org.apache.flink.table.factories.TableFactory的文件,将com.bigdata.connect.redis.RedisTableFactory写入,如果还有自定义的其他source/sink也一起写在这里

5.打包发布

注意打包的时候一定要确认把com.bigdata.connect.redis.RedisTableFactory打进去了,最好打包完反编译一下看时候被覆盖。我使用maven-assembly-plugin打包就会出现被覆盖的问题,后面改为maven-shade-plugin打包就没问题,所以一定要检查下。

6.遇到的问题

org.apache.flink.table.api.TableException: Table sink does not implement a table schema.

在RedisTableSink中忘记重写getTableSchema方法

org.apache.flink.table.api.TableException: Table sink does not implement a consumed data type.

在RedisTableSink中忘记重写getConsumedDataType方法

org.apache.flink.api.common.InvalidProgramException: root
|-- pay_hour: STRING
|-- item_id: STRING
is not serializable. The object probably contains or references non serializable fields.

在RedisTableSink的emitDataStream方法中将tableSchema传到RedisSinkFunction方法中去,而TableSchema未实现Serializable,出现序列化的问题

org.apache.flink.client.program.ProgramInvocationException: The main method caused an error: The StreamTableSink#consumeDataStream(DataStream) must be implemented and return the sink transformation DataStreamSink. However, com.bigdata.connect.redis.RedisTableSink doesn't implement this method.

使用了废弃的emitDataStream方法,而且没有重写consumeDataStream

7.使用方式

sink使用方法:

 

参考文档

https://ci.apache.org/projects/flink/flink-docs-release-1.10/dev/table/sourceSinks.html

posted @ 2022-08-10 15:27  博而不客  阅读(693)  评论(0编辑  收藏  举报