├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
└── main
├── java
└── org
│ └── apache
│ └── flink
│ └── api
│ └── java
│ └── io
│ └── redis
│ ├── RedisInputFormat.java
│ ├── RedisLookupFunction.java
│ ├── RedisOptions.java
│ ├── RedisOutFormat.java
│ ├── RedisRetractTableSink.java
│ ├── RedisSinkFunction.java
│ ├── RedisSourceSinkFactory.java
│ └── RedisTableSource.java
└── resources
└── META-INF
└── services
└── org.apache.flink.table.factories.TableFactory
/.gitignore:
--------------------------------------------------------------------------------
1 | .cache
2 | scalastyle-output.xml
3 | .classpath
4 | .idea/*
5 | .metadata
6 | .settings
7 | .project
8 | .version.properties
9 | filter.properties
10 | logs.zip
11 | target
12 | tmp
13 | *.class
14 | *.iml
15 | *.swp
16 | *.jar
17 | *.log
18 | .DS_Store
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 DinoZhang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # flink-connector-redis
2 | 基于`Blink`的`Flink SQL Redis`连接器,支持`Redis`维表和结果表。
3 |
4 | [](http://hits.dwyl.com/DinoZhang/DinoZhang/flink-connector-redis)
5 |
6 |
7 |
8 | ## 安装
9 | ```shell
10 | mvn clean package -Pfast
11 | ```
12 | 打包完成后,将`flink-jdbc-1.5.1.jar`和`jedis-2.7.2.jar`拷贝至`Fink lib`目录下。
13 | ## 使用
14 | ### 维表
15 | ```sql
16 | create table redis_dim (
17 | k varchar,
18 | v varchar,
19 | primary key(k)
20 | ) with (
21 | type = 'redis',
22 | host = '127.0.0.1',
23 | port = '6379',
24 | password = ''
25 | );
26 | ```
27 | ### 结果表
28 | 支持String类型,等价于`set key value`。
29 | ```sql
30 | create table redis_sink (
31 | k varchar,
32 | v varchar,
33 | primary key(k)
34 | ) with (
35 | type = 'redis',
36 | host = '127.0.0.1',
37 | port = '6379',
38 | password = '',
39 | db = '0'
40 | );
41 | ```
42 | ### 示例
43 | ```sql
44 | create table kafka_source (
45 | messageKey varbinary,
46 | message varbinary,
47 | topic varchar,
48 | `partition` int,
49 | `offset` bigint
50 | ) with (
51 | type = 'kafka010',
52 | topic = 'test',
53 | bootstrap.servers = 'localhost:9092',
54 | `group.id` = 'sql_group_1'
55 | );
56 |
57 | create table redis_sink (
58 | k varchar,
59 | v varchar,
60 | primary key(k)
61 | ) with (
62 | type = 'redis',
63 | host = '127.0.0.1',
64 | port = '6379',
65 | password = '',
66 | db = '0'
67 | );
68 |
69 | insert into redis_sink
70 | select cast(`offset` as varchar),cast(CURRENT_TIMESTAMP as varchar) from kafka_source;
71 |
72 | ```
73 |
74 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | flink-connectors
7 | com.alibaba.blink
8 | 1.5.1
9 |
10 | 4.0.0
11 |
12 | flink-connector-redis
13 |
14 | 2.11
15 |
16 |
17 |
18 |
19 |
20 | com.alibaba.blink
21 | flink-table_${scala.binary.version}
22 | ${project.version}
23 | provided
24 |
26 | true
27 |
28 |
29 |
30 | com.alibaba.blink
31 | flink-streaming-java_${scala.binary.version}
32 | ${project.version}
33 | provided
34 |
35 |
36 | redis.clients
37 | jedis
38 | 2.7.2
39 | jar
40 | compile
41 |
42 |
43 |
44 | com.alibaba.blink
45 | flink-scala_${scala.binary.version}
46 | ${project.version}
47 | test
48 |
49 |
50 |
51 | org.apache.derby
52 | derby
53 | 10.14.2.0
54 | test
55 |
56 |
57 |
58 | commons-codec
59 | commons-codec
60 | 1.10
61 |
62 |
63 | junit
64 | junit
65 |
66 |
67 |
68 |
69 |
70 |
71 | com.alibaba.blink
72 | flink-streaming-scala_${scala.binary.version}
73 | ${project.version}
74 | test
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/src/main/java/org/apache/flink/api/java/io/redis/RedisInputFormat.java:
--------------------------------------------------------------------------------
1 | package org.apache.flink.api.java.io.redis;
2 |
3 | import org.apache.flink.api.common.io.RichInputFormat;
4 | import org.apache.flink.api.common.io.statistics.BaseStatistics;
5 | import org.apache.flink.api.common.typeinfo.TypeInformation;
6 | import org.apache.flink.api.java.typeutils.ResultTypeQueryable;
7 | import org.apache.flink.api.java.typeutils.RowTypeInfo;
8 | import org.apache.flink.configuration.Configuration;
9 | import org.apache.flink.core.io.InputSplit;
10 | import org.apache.flink.core.io.InputSplitAssigner;
11 | import org.apache.flink.hive.shaded.org.apache.commons.lang3.StringUtils;
12 | import org.apache.flink.types.Row;
13 |
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 | import redis.clients.jedis.Jedis;
17 |
18 | import java.io.IOException;
19 |
20 | /**
21 | * @version $Id: RedisInputFormat.java, v 0.1 2019年11月29日 11:05 AM Exp $
22 | */
23 | public class RedisInputFormat extends RichInputFormat implements ResultTypeQueryable {
24 |
25 | private static final long serialVersionUID = -5714715362124636647L;
26 | private RowTypeInfo rowTypeInfo;
27 | private static Logger log = LoggerFactory.getLogger(RedisOutFormat.class);
28 | private Jedis jedis;
29 | private String host;
30 | private int port;
31 | private String password;
32 |
33 | public RedisInputFormat(final String host, final int port, final String password) {
34 | this.host = host;
35 | this.port = port;
36 | this.password = password;
37 | }
38 |
39 | @Override
40 | public void configure(final Configuration parameters) {
41 |
42 | }
43 |
44 | @Override
45 | public BaseStatistics getStatistics(final BaseStatistics cachedStatistics) throws IOException {
46 | return null;
47 | }
48 |
49 | @Override
50 | public InputSplit[] createInputSplits(final int minNumSplits) throws IOException {
51 | return new InputSplit[0];
52 | }
53 |
54 | @Override
55 | public InputSplitAssigner getInputSplitAssigner(final InputSplit[] inputSplits) {
56 | return null;
57 | }
58 |
59 | @Override
60 | public void open(final InputSplit split) throws IOException {
61 | }
62 |
63 | @Override
64 | public boolean reachedEnd() throws IOException {
65 | return false;
66 | }
67 |
68 | @Override
69 | public Row nextRecord(final Row reuse) throws IOException {
70 | return null;
71 | }
72 |
73 | @Override
74 | public void close() throws IOException {
75 | jedis.close();
76 | }
77 |
78 | @Override
79 | public TypeInformation getProducedType() {
80 | return rowTypeInfo;
81 | }
82 |
83 | public Jedis getRedisConnection(){
84 | return jedis;
85 | }
86 |
87 | @Override
88 | public void openInputFormat() throws IOException {
89 | try {
90 | jedis = new Jedis(host, port);
91 | if (StringUtils.isNotBlank(password)) {
92 | jedis.auth(password);
93 | }
94 |
95 | } catch (Exception se) {
96 | throw new IllegalArgumentException("redis input open() failed." + se.getMessage(), se);
97 | }
98 | }
99 |
100 | @Override
101 | public void closeInputFormat() throws IOException {
102 | if (jedis != null){
103 | jedis.close();
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/main/java/org/apache/flink/api/java/io/redis/RedisLookupFunction.java:
--------------------------------------------------------------------------------
1 | package org.apache.flink.api.java.io.redis;
2 |
3 | import org.apache.flink.table.api.functions.FunctionContext;
4 | import org.apache.flink.table.api.functions.TableFunction;
5 | import org.apache.flink.table.api.types.DataType;
6 | import org.apache.flink.table.dataformat.BinaryString;
7 | import org.apache.flink.types.Row;
8 |
9 | /**
10 | * @version $Id: RedisLookupFunction.java, v 0.1 2019年11月24日 5:51 PM Exp $
11 | */
12 | public class RedisLookupFunction extends TableFunction {
13 |
14 | private RedisInputFormat redisInputFormat;
15 |
16 | public RedisLookupFunction(final RedisInputFormat redisInputFormat) {
17 | this.redisInputFormat = redisInputFormat;
18 | }
19 |
20 | @Override
21 | public DataType getResultType(final Object[] arguments, final Class[] argTypes) {
22 | return super.getResultType(arguments, argTypes);
23 | }
24 |
25 | @Override
26 | public void open(final FunctionContext context) throws Exception {
27 | redisInputFormat.openInputFormat();
28 | }
29 |
30 | public void eval(Object... key) {
31 | //redisInputFormat.
32 | String result = redisInputFormat.getRedisConnection().get(BinaryString.fromString(key[0]).toString());
33 | if (result != null){
34 | Row row = new Row(2);
35 | row.setField(0, BinaryString.fromString(key[0]).toString());
36 | row.setField(1, result);
37 | collect(row);
38 | }
39 | }
40 |
41 | @Override
42 | public void close() throws Exception {
43 | super.close();
44 | redisInputFormat.close();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/apache/flink/api/java/io/redis/RedisOptions.java:
--------------------------------------------------------------------------------
1 | package org.apache.flink.api.java.io.redis;
2 |
3 | import org.apache.flink.configuration.ConfigOption;
4 |
5 | import java.util.Arrays;
6 | import java.util.List;
7 |
8 | import static org.apache.flink.configuration.ConfigOptions.key;
9 |
10 |
11 |
12 | /**
13 | * Options for redis.
14 | */
15 | public class RedisOptions {
16 |
17 |
18 |
19 |
20 | public static final ConfigOption HOST = key("host".toLowerCase()).noDefaultValue();
21 | public static final ConfigOption PORT = key("port".toLowerCase()).noDefaultValue();
22 | public static final ConfigOption PASSWORD = key("password".toLowerCase()).noDefaultValue();
23 | public static final ConfigOption BATH_SIZE = key("batchsize".toLowerCase()).noDefaultValue();
24 | public static final ConfigOption DB = key("db".toLowerCase()).noDefaultValue();
25 |
26 |
27 | public static final List SUPPORTED_KEYS = Arrays.asList(PASSWORD.key(), HOST.key(), PORT.key(), BATH_SIZE.key(), DB.key());
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/org/apache/flink/api/java/io/redis/RedisOutFormat.java:
--------------------------------------------------------------------------------
1 | package org.apache.flink.api.java.io.redis;
2 |
3 | import org.apache.flink.api.common.io.RichOutputFormat;
4 | import org.apache.flink.configuration.Configuration;
5 | import org.apache.flink.hive.shaded.org.apache.commons.lang3.StringUtils;
6 | import org.apache.flink.types.Row;
7 |
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 | import redis.clients.jedis.Jedis;
11 |
12 | import java.io.IOException;
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | /**
17 | * @version $Id: RedisOutFormat.java, v 0.1 2019年11月29日 11:05 AM Exp $
18 | */
19 | public class RedisOutFormat extends RichOutputFormat {
20 |
21 | private static final long serialVersionUID = -3819462971300769382L;
22 |
23 | private static Logger log = LoggerFactory.getLogger(RedisOutFormat.class);
24 | private Jedis jedis;
25 | private List cache = new ArrayList();
26 | private int batchsize;
27 | private String host;
28 | private int port;
29 | private String password;
30 | private int db;
31 |
32 | public RedisOutFormat(final int batchsize, final String host, final int port, final String password, final int db) {
33 | this.batchsize = batchsize;
34 | this.host = host;
35 | this.port = port;
36 | this.password = password;
37 | this.db = db;
38 | }
39 |
40 | @Override
41 | public void configure(final Configuration parameters) {
42 | }
43 |
44 | @Override
45 | public void open(final int taskNumber, final int numTasks) throws IOException {
46 | log.info(String.format("Open Method Called: taskNumber %d numTasks %d", taskNumber, numTasks));
47 | batchsize = batchsize > 0 ? batchsize : 1;
48 | try {
49 | jedis = new Jedis(host, port);
50 | if (StringUtils.isNotBlank(password)) {
51 | jedis.auth(password);
52 | }
53 | jedis.select(db);
54 | } catch (Exception e) {
55 | throw new IllegalArgumentException("redis open() failed.", e);
56 | }
57 |
58 | }
59 |
60 | @Override
61 | public void writeRecord(final Row record) throws IOException {
62 | String key = record.getField(0).toString();
63 | String value = record.getField(1).toString();
64 | //log.info("key:" + key + ",value:" + value);
65 | try {
66 | cache.add(record);
67 | if (cache.size() >= batchsize) {
68 | for (int i = 0; i < cache.size(); i++) {
69 | jedis.set(key, value);
70 | }
71 | cache.clear();
72 | }
73 | } catch (Exception e) {
74 | throw new IllegalArgumentException("redis write() failed.", e);
75 | }
76 |
77 | }
78 |
79 | @Override
80 | public void close() throws IOException {
81 | try {
82 | jedis.quit();
83 | jedis.close();
84 | } catch (Exception e) {
85 | throw new IllegalArgumentException("redis close() failed.", e);
86 | }
87 |
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/org/apache/flink/api/java/io/redis/RedisRetractTableSink.java:
--------------------------------------------------------------------------------
1 |
2 | package org.apache.flink.api.java.io.redis;
3 |
4 | import org.apache.flink.api.common.functions.FlatMapFunction;
5 | import org.apache.flink.api.java.tuple.Tuple2;
6 | import org.apache.flink.streaming.api.datastream.DataStream;
7 | import org.apache.flink.streaming.api.datastream.DataStreamSink;
8 | import org.apache.flink.table.api.types.DataType;
9 | import org.apache.flink.table.api.types.DataTypes;
10 | import org.apache.flink.table.sinks.RetractStreamTableSink;
11 | import org.apache.flink.table.sinks.TableSink;
12 | import org.apache.flink.table.util.TableConnectorUtil;
13 | import org.apache.flink.types.Row;
14 | import org.apache.flink.util.Collector;
15 | import org.apache.flink.util.InstantiationUtil;
16 |
17 |
18 | /**
19 | * @version $Id: RedisRetractTableSink.java, v 0.1 2019年12月04日 10:43 AM Exp $
20 | */
21 | public class RedisRetractTableSink implements RetractStreamTableSink {
22 | private final RedisOutFormat outputFormat;
23 |
24 | private String[] fieldNames;
25 | private DataType[] fieldTypes;
26 |
27 | /**
28 | * Setter method for property fieldNames.
29 | *
30 | * @param fieldNames value to be assigned to property fieldNames
31 | */
32 | public void setFieldNames(final String[] fieldNames) {
33 | this.fieldNames = fieldNames;
34 | }
35 |
36 | /**
37 | * Setter method for property fieldTypes.
38 | *
39 | * @param fieldTypes value to be assigned to property fieldTypes
40 | */
41 | public void setFieldTypes(final DataType[] fieldTypes) {
42 | this.fieldTypes = fieldTypes;
43 | }
44 |
45 | public RedisRetractTableSink(final RedisOutFormat outputFormat) {
46 | this.outputFormat = outputFormat;
47 | }
48 |
49 | @Override
50 | public DataType getRecordType() {
51 | return null;
52 | }
53 |
54 | @Override
55 | public DataType getOutputType() {
56 | DataType outputType = DataTypes.createRowType(fieldTypes, fieldNames);
57 |
58 | return DataTypes.createTupleType(DataTypes.BOOLEAN, outputType);
59 | }
60 |
61 | @Override
62 | public DataStreamSink> emitDataStream(final DataStream> dataStream) {
63 |
64 | return dataStream.flatMap(new FlatMapFunction, Row>() {
65 | @Override
66 | public void flatMap(final Tuple2 value, final Collector out) throws Exception {
67 | if (value.f0) {
68 | out.collect(value.f1);
69 | }
70 |
71 | }
72 | }).addSink(new RedisSinkFunction(outputFormat)).name(TableConnectorUtil.generateRuntimeName(this.getClass(), fieldNames));
73 | }
74 |
75 | @Override
76 | public String[] getFieldNames() {
77 | return fieldNames;
78 | }
79 |
80 | @Override
81 | public DataType[] getFieldTypes() {
82 | return fieldTypes;
83 | }
84 |
85 | @Override
86 | public TableSink> configure(final String[] fieldNames, final DataType[] fieldTypes) {
87 | RedisRetractTableSink copy = null;
88 | try {
89 | copy = new RedisRetractTableSink(InstantiationUtil.clone(outputFormat));
90 | copy.setFieldTypes(fieldTypes);
91 | copy.setFieldNames(fieldNames);
92 | } catch (Exception e) {
93 | throw new RuntimeException(e);
94 | }
95 | return copy;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/main/java/org/apache/flink/api/java/io/redis/RedisSinkFunction.java:
--------------------------------------------------------------------------------
1 | package org.apache.flink.api.java.io.redis;
2 |
3 | import org.apache.flink.api.common.functions.RuntimeContext;
4 | import org.apache.flink.configuration.Configuration;
5 | import org.apache.flink.metrics.Counter;
6 | import org.apache.flink.streaming.api.functions.sink.RichSinkFunction;
7 | import org.apache.flink.types.Row;
8 |
9 | /**
10 | * @version $Id: RedisSinkFunction.java, v 0.1 2019年12月04日 11:05 AM Exp $
11 | */
12 | public class RedisSinkFunction extends RichSinkFunction {
13 |
14 | private RedisOutFormat redisOutFormat;
15 | private Counter counter;
16 |
17 | public RedisSinkFunction(final RedisOutFormat redisOutFormat) {
18 | this.redisOutFormat = redisOutFormat;
19 | }
20 |
21 | @Override
22 | public void invoke(final Row value, final Context context) throws Exception {
23 | redisOutFormat.writeRecord(value);
24 | counter.inc();
25 | }
26 |
27 | @Override
28 | public void open(final Configuration parameters) throws Exception {
29 | super.open(parameters);
30 | RuntimeContext ctx = getRuntimeContext();
31 | redisOutFormat.setRuntimeContext(ctx);
32 | this.counter = getRuntimeContext().getMetricGroup().counter("RedisSink");
33 | }
34 |
35 | @Override
36 | public void close() throws Exception {
37 | super.close();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/org/apache/flink/api/java/io/redis/RedisSourceSinkFactory.java:
--------------------------------------------------------------------------------
1 | package org.apache.flink.api.java.io.redis;
2 |
3 | import org.apache.flink.api.java.typeutils.TupleTypeInfo;
4 | import org.apache.flink.table.api.RichTableSchema;
5 | import org.apache.flink.table.factories.StreamTableSinkFactory;
6 | import org.apache.flink.table.factories.StreamTableSourceFactory;
7 | import org.apache.flink.table.sinks.StreamTableSink;
8 | import org.apache.flink.table.sources.StreamTableSource;
9 | import org.apache.flink.table.util.TableProperties;
10 | import org.apache.flink.types.Row;
11 |
12 | import java.util.HashMap;
13 | import java.util.HashSet;
14 | import java.util.List;
15 | import java.util.Map;
16 | import java.util.Set;
17 |
18 | import static org.apache.flink.api.java.io.redis.RedisOptions.SUPPORTED_KEYS;
19 | import static org.apache.flink.table.descriptors.ConnectorDescriptorValidator.CONNECTOR_PROPERTY_VERSION;
20 | import static org.apache.flink.table.descriptors.ConnectorDescriptorValidator.CONNECTOR_TYPE;
21 |
22 | /**
23 | * @version $Id: RedisSourceSinkFactory.java, v 0.1 2019年11月29日 10:29 AM Exp $
24 | */
25 | public class RedisSourceSinkFactory implements StreamTableSourceFactory, StreamTableSinkFactory {
26 | @Override
27 | public StreamTableSink createStreamTableSink(final Map props) {
28 | TableProperties properties = new TableProperties();
29 | properties.putProperties(props);
30 | RichTableSchema schema = properties.readSchemaFromProperties(null);
31 |
32 | String host = properties.getString(RedisOptions.HOST);
33 | int port = properties.getInteger(RedisOptions.PORT.key(), 6349);
34 | String password = properties.getString(RedisOptions.PASSWORD);
35 | int db = properties.getInteger(RedisOptions.DB.key(), 0);
36 | int batchSize = properties.getInteger(RedisOptions.BATH_SIZE.key(), 1);
37 |
38 | RedisOutFormat redisOutFormat = new RedisOutFormat(batchSize, host, port, password, db);
39 |
40 | RedisRetractTableSink redisRetractTableSink = new RedisRetractTableSink(redisOutFormat);
41 | redisRetractTableSink.setFieldNames(schema.getColumnNames());
42 | redisRetractTableSink.setFieldTypes(schema.getColumnTypes());
43 |
44 | return (StreamTableSink) redisRetractTableSink.configure(schema.getColumnNames(), schema.getColumnTypes());
45 | }
46 |
47 | @Override
48 | public StreamTableSource createStreamTableSource(final Map props) {
49 | TableProperties properties = new TableProperties();
50 | properties.putProperties(props);
51 | RichTableSchema schema = properties.readSchemaFromProperties(null);
52 |
53 | String host = properties.getString(RedisOptions.HOST);
54 | int port = properties.getInteger(RedisOptions.PORT.key(), 6349);
55 | String password = properties.getString(RedisOptions.PASSWORD);
56 |
57 | Set> uniqueKeys = new HashSet<>();
58 | Set> normalIndexes = new HashSet<>();
59 | if (!schema.getPrimaryKeys().isEmpty()) {
60 | uniqueKeys.add(new HashSet<>(schema.getPrimaryKeys()));
61 | }
62 | for (List uniqueKey : schema.getUniqueKeys()) {
63 | uniqueKeys.add(new HashSet<>(uniqueKey));
64 | }
65 | for (RichTableSchema.Index index : schema.getIndexes()) {
66 | if (index.unique) {
67 | uniqueKeys.add(new HashSet<>(index.keyList));
68 | } else {
69 | normalIndexes.add(new HashSet<>(index.keyList));
70 | }
71 | }
72 |
73 | RedisInputFormat redisInputFormat = new RedisInputFormat(host, port, password);
74 |
75 | RedisTableSource redisTableSource = new RedisTableSource(schema, redisInputFormat, uniqueKeys, normalIndexes);
76 |
77 | return redisTableSource;
78 | }
79 |
80 | @Override
81 | public Map requiredContext() {
82 | Map context = new HashMap<>();
83 | context.put(CONNECTOR_TYPE, "REDIS");
84 | context.put(CONNECTOR_PROPERTY_VERSION, "1");
85 | return context;
86 | }
87 |
88 | @Override
89 | public List supportedProperties() {
90 | return SUPPORTED_KEYS;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/org/apache/flink/api/java/io/redis/RedisTableSource.java:
--------------------------------------------------------------------------------
1 | package org.apache.flink.api.java.io.redis;
2 |
3 | import org.apache.flink.streaming.api.datastream.DataStream;
4 | import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
5 | import org.apache.flink.table.api.RichTableSchema;
6 | import org.apache.flink.table.api.TableSchema;
7 | import org.apache.flink.table.api.functions.AsyncTableFunction;
8 | import org.apache.flink.table.api.functions.TableFunction;
9 | import org.apache.flink.table.api.types.DataType;
10 | import org.apache.flink.table.plan.stats.TableStats;
11 | import org.apache.flink.table.sources.LookupConfig;
12 | import org.apache.flink.table.sources.LookupableTableSource;
13 | import org.apache.flink.table.sources.StreamTableSource;
14 | import org.apache.flink.types.Row;
15 |
16 | import java.util.Set;
17 |
18 | /**
19 | * @version $Id: RedisTableSource.java, v 0.1 2019年12月04日 6:14 PM Exp $
20 | */
21 | public class RedisTableSource implements LookupableTableSource, StreamTableSource {
22 |
23 | private RichTableSchema tableSchema; // for table type info
24 |
25 |
26 | private RedisInputFormat redisInputFormat;
27 | private Set> uniqueKeySet;
28 | private Set> indexKeySet;
29 |
30 | public RedisTableSource(final RichTableSchema tableSchema, final RedisInputFormat redisInputFormat, final Set> uniqueKeySet, final Set> indexKeySet) {
31 | this.tableSchema = tableSchema;
32 | this.redisInputFormat = redisInputFormat;
33 | this.uniqueKeySet = uniqueKeySet;
34 | this.indexKeySet = indexKeySet;
35 | }
36 |
37 | @Override
38 | public TableFunction getLookupFunction(final int[] lookupKeys) {
39 | return new RedisLookupFunction(redisInputFormat);
40 | }
41 |
42 | @Override
43 | public AsyncTableFunction getAsyncLookupFunction(final int[] lookupKeys) {
44 | return null;
45 | }
46 |
47 | @Override
48 | public LookupConfig getLookupConfig() {
49 | return null;
50 | }
51 |
52 | @Override
53 | public DataStream getDataStream(final StreamExecutionEnvironment execEnv) {
54 | return null;
55 | }
56 |
57 | @Override
58 | public DataType getReturnType() {
59 | return tableSchema.getResultRowType();
60 | }
61 |
62 | @Override
63 | public TableSchema getTableSchema() {
64 | TableSchema.Builder builder = TableSchema.builder();
65 |
66 | // uniqueKeySet.toArray(new String[uniqueKeySet.size()]);
67 |
68 | // HashSet[] uniqueKeySettemp = uniqueKeySet.toArray(new HashSet[uniqueKeySet.size()]);
69 |
70 | // indexKeySet.forEach(indexKey ->builder.uniqueIndex(indexKeySet.toArray(new String[indexKeySet.size()])));
71 | // builder.uniqueKey("pv");
72 | for (int i = 0; i < tableSchema.getColumnNames().length; i++) {
73 |
74 | builder.column(tableSchema.getColumnNames()[i], tableSchema.getColumnTypes()[i], tableSchema.getNullables()[i]);
75 |
76 | }
77 |
78 | /// ..foreach(c => builder.field(c.name, c.internalType, c.isNullable))
79 |
80 | if (uniqueKeySet != null) {
81 | uniqueKeySet.forEach(uniqueKey -> builder.uniqueIndex(uniqueKey.toArray((new String[0]))));
82 | indexKeySet.forEach(indexKey -> builder.normalIndex(indexKey.toArray((new String[0]))));
83 | }
84 | return new TableSchema(builder.build().getColumns(), builder.build().getPrimaryKeys(), builder.build().getUniqueKeys(), builder.build().getUniqueIndexes(), null, null);
85 | }
86 |
87 | @Override
88 | public String explainSource() {
89 | return "Redis";
90 | }
91 |
92 | @Override
93 | public TableStats getTableStats() {
94 | return null;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/services/org.apache.flink.table.factories.TableFactory:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one or more
2 | # contributor license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright ownership.
4 | # The ASF licenses this file to You under the Apache License, Version 2.0
5 | # (the "License"); you may not use this file except in compliance with
6 | # the License. You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | org.apache.flink.api.java.io.redis.RedisSourceSinkFactory
17 |
--------------------------------------------------------------------------------