Flink源码剖析:自定义TableSink与TableFactory定位过程剖析

1. 背景

现有自定义redis sink的需求,我们借此学习一下如何自定义flink sink connector,以及flink是如何通过ddl建表语句中的properties来定位具体的TableFactory,进而创建StreamTableSink的。

该文介绍的写法是Flink1.10之前的写法,Flink1.11之后的版本在兼容该文所介绍的写法的同时,对用户自定义Source和Sink相关逻辑进行了重构,详情请参考官方文档。

2. user-defined redis sink

文中代码详情请参考github

如果只是利用DataStream API定义一个sink connector,则实现SinkFunction接口,然后调用datastream.addSink(redisSink)即可,详情参考源码中的RedisSinkITCase#testRedisListDataType测试用例。

如果想要在Table API / SQL DDL中使用自定义sink connector,则需要依次实现
TableSinkFactory -> TableSink -> SinkFunction

2.1 RedisTableSinkFactory

Flink使用SPI查找到ClassPath下所有的TableSinkFactory class对象(下节详细介绍),并通过DDL中定义的properties来查找需要实例化的具体TableSinkFactory。

/**
 * redis table sink factory for creare redis table sink.
 */
public class RedisTableSinkFactory implements StreamTableSinkFactory<Tuple2<Boolean, Row>> {
   

	// 将DDL中的属性解析成入参properties,并创建TableSink
    @Override
    public StreamTableSink<Tuple2<Boolean, Row>> createStreamTableSink(Map<String, String> properties) {
   
        return new RedisTableSink(properties);
    }

	// 根据这里定义的属性,从众多TableSinkFactory实例中精确定位需要使用的TableSinkFactory
    @Override
    public Map<String, String> requiredContext() {
   
        Map<String, String> require = new HashMap<>();
        require.put(CONNECTOR_TYPE, REDIS);
        return require;
    }

	// 预先定义可以写在DDL中的properties,如果在TableSinkFactory查找过程中,发现DDL中properties全部属于在此定义的properties,则认为该TableFactory即为要使用的TableFactory
	// 可以认为,supportedProperties()方法中的properties和requiredContext()方法中的properties都是用来精确定位TableSinkFactory实现类的
    @Override
    public List<String> supportedProperties() {
   
        List<String> properties = new ArrayList<>();
        properties.add(REDIS_MODE);
        properties.add(REDIS_COMMAND);
        properties.add(REDIS_NODES);
        properties.add(REDIS_MASTER_NAME);
        properties.add(REDIS_SENTINEL);
        properties.add(REDIS_KEY_TTL);
        // schema
        properties.add(SCHEMA + ".#." + SCHEMA_DATA_TYPE);
        properties.add(SCHEMA + ".#." + SCHEMA_NAME);
        // format wildcard
        properties.add(CONNECTOR + ".*");
        // standalone
        properties.add(REDIS_SERVER_IP);
        properties.add(REDIS_SERVER_PORT);
        return properties;
    }
}

2.2 RedisTableSink

通过SPI定位到具体TableFactory之后,会创建TableSink并消费上游的流数据。

public class RedisTableSink implements UpsertStreamTableSink<Row> {
   
...
	// 创建SinkFunction
    @Override
    public DataS
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值