Flink写入Redis的两种方式

1、使用flink提供的RedisSink

(1)添加maven依赖

<dependency>
   <groupId>org.apache.bahir</groupId>
   <artifactId>flink-connector-redis_2.11</artifactId>
   <version>1.1-SNAPSHOT</version>
</dependency>

(2)实现一个redisMapper

创建一个类,继承 RedisMapper<T>接口,如下代码示例所示,

public static class RedisExampleMapper implements RedisMapper<Tuple2<String, String>>{

    @Override
    public RedisCommandDescription getCommandDescription() {
        return new RedisCommandDescription(RedisCommand.HSET, "HASH_NAME");
    }

    @Override
    public String getKeyFromData(Tuple2<String, String> data) {
        return data.f0;
    }

    @Override
    public String getValueFromData(Tuple2<String, String> data) {
        return data.f1;
    }
}

 注意了,如果使用Hash类型的话,这里的Hash key就得写死,也就是说这个key不能动态的从接收到的数据中获取(太别扭了,不知道还有没有其他动态设置的方式,有则劳烦告知)

下面分别讲一下这里实现的这三个方法

  • RedisCommandDescription()方法用于指定对接收来的数据进行什么操作,示例中指定为HSET操作,也可以指定为SET操作等等,另外指定HSET操作时需要跟上key参数。
  • getKeyFromData()方法用于指定接收到的数据中哪部分作为key,示例中,是将数据源中元组数据的第一个值作为key
  • getValueFromData()方法用于指定接收到的数据中哪部分作为value,示例中,是将数据源中元组数据的第二个值作为value

(3)通过addSink()方法将实现的RedisSink添加到流上

1、注意先创建好redis连接配置对象,因为创建redisSink时会用到

FlinkJedisPoolConfig conf = new FlinkJedisPoolConfig.Builder().setHost("127.0.0.1").build();

 2、添加到流中

DataStream<String> stream = ...;
stream.addSink(new RedisSink<Tuple2<String, String>>(conf, new RedisExampleMapper());

2、自定义Sink

(1)创建一个类,继承RichSinkFunction,这个类就是自定义实现的sink

 
public class RedisSinkCustom extends RichSinkFunction<avro.ScadaData> {

    Configuration parameters;
    Jedis jedis = null;
    byte[] valueKey = "value".getBytes();
    byte[] qualitykey = "quality".getBytes();
    byte[] timeKey = "time".getBytes();
    public RedisSinkCustom(Configuration parameters){
        this.parameters = parameters;
    }

    
    @Override
    public void open(Configuration parameters) throws Exception {
        super.open(this.parameters);
        jedis = new Jedis(this.parameters.getString("host","hadoop"),
                this.parameters.getInteger("port",6379));
    }

    @Override
    public void invoke(ScadaData value, Context context) {
        int dataType = value.getDatatype();
        List<avro.SRtValue> datas = value.getData();
        String tabName = null;
        switch (dataType){
            case 1:tabName = "s_analog";break;
            case 2:tabName = "s_discrete";break;
        }
        byte[] hkey = null;
        for(avro.SRtValue data:datas){
            hkey = new StringBuffer(tabName).append(".").append(data.getId()).toString().getBytes();
            jedis.hset(hkey,valueKey,String.valueOf(data.getV()).getBytes());
            jedis.hset(hkey,qualitykey,String.valueOf(data.getQ()).getBytes());
            jedis.hset(hkey,timeKey,String.valueOf(data.getTime()).getBytes());
        }
    }

    @Override
    public void close() throws Exception {
        super.close();
        jedis.close();
    }

继承RichSinkFunction类后,主要重写三个方法 ,分别为:open(),invok(),close()

  • open()方法在创建sink时候只调用一次,所以这里可以用于初始化一些资源配置,我这里创建了redis的连接
  • invok(Object value, Context context)方法在每次有数据流入时都会调用,所以从源中每过来一个数据都会执行,value参数即为流中的数据元素
  • close()方法用于关闭sink时调用,一般用于释放资源

 

(2)将自定义sink添加到流上 

DataStream<ScadaData> stream = ...
stream.addSink(new RedisSinkCustom(conf));

(我这里给sink传入的conf参数是我自定义的用来配置redis连接信息的)

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

头顶榴莲树

你的鼓励是我最大的动力~

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

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

打赏作者

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

抵扣说明:

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

余额充值