Flink SQL实战

最近在研究Flink SQL流,这里写一个简单的实战。

背景

每1分钟统计过去1个小时,各个商品的购买量。

数据格式为{"behavior":"cart","itemId":19,"nowTime":1562314387553}

behavior:为用户行为,有cart,pv,buy。我们这里要的就是buy

代码

import com.alibaba.fastjson.JSON;
import com.closeli.writetohbase.fun.SQLKEYPro;
import com.closeli.writetohbase.fun.UDFToTime;
import com.closeli.writetohbase.fun.UserWaterMark;
import com.closeli.writetohbase.pojo.UserData;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.api.common.typeinfo.TypeHint;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.streaming.api.TimeCharacteristic;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer010;
import org.apache.flink.table.api.Table;
import org.apache.flink.table.api.TableEnvironment;
import org.apache.flink.table.api.java.StreamTableEnvironment;


import java.util.Properties;

public class SQLTOKafka {

    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        StreamTableEnvironment tEnv = TableEnvironment.getTableEnvironment(env);

        env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
        Properties prop = new Properties();
        prop.put("group.id","aaaaaaa");
        prop.put("bootstrap.servers","node223:6667,node224:6667,node225:6667");

        FlinkKafkaConsumer010<String> consumer = new FlinkKafkaConsumer010<>("mydata", new SimpleStringSchema(), prop);
        DataStreamSource<String> dataSource = env.addSource(consumer);


//        dataSource.print();

        SingleOutputStreamOperator<UserData> filterData = dataSource.map(new MapFunction<String, UserData>() {
            @Override
            public UserData map(String value) throws Exception {
                UserData userData = null;
                try {
                    userData = JSON.parseObject(value, UserData.class);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return userData;
            }
        }).filter(x -> x != null && x.getBehavior().equals("pv")).assignTimestampsAndWatermarks(new UserWaterMark());

        //自定义UDF,将时间戳改成东八区的形式
        tEnv.registerFunction("timetoformat",new UDFToTime());
        
        tEnv.registerDataStream("userTable",filterData,"behavior,itemId,nowTime.rowTime");
//        Table table = tEnv.sqlQuery("select url,count(1) from userTable group by TUMBLE(nowTime,INTERVAL '5' SECOND),url");
        Table table = tEnv.sqlQuery("select itemId,count(1),timetoformat(HOP_END(nowTime,  INTERVAL '10' SECOND, INTERVAL '30' MINUTE)) from userTable group by HOP(nowTime, INTERVAL '10' SECOND, INTERVAL '30' MINUTE),itemId");

//        DataStream<Tuple> resultData = tEnv.toAppendStream(table, Types.TUPLE(Types.INT, Types.LONG ,Types.SQL_TIMESTAMP));
//        DataStream<Tuple> resultData = tEnv.toAppendStream(table, Types.TUPLE(Types.INT, Types.LONG ,Types.LONG));

        DataStream<Tuple3<Integer, Long, Long>> resultData = tEnv.toAppendStream(table, TypeInformation.of(new TypeHint<Tuple3<Integer, Long, Long>>() {}));

        resultData.print();

        
        env.execute("SQLTOKafka");
    }
}

UserData

是一个pojo类,属性是behavior、itemId、nowTime

UDFToTime

这个是自定义的UDF,负责将timestamp转成东八区的时间,Flink SQL中的时间距离北京时间差了8个小时,所以,如果后续有需要,可以进行转换。

import org.apache.flink.table.functions.ScalarFunction;

import java.sql.Timestamp;

public class UDFToTime extends ScalarFunction {

    public Long eval(Timestamp s){
        return s.getTime() + 28800000;
    }

}

 注意点

1、目前Flinik SQL在流式处理中不支持limit 。对于order by,说是只可以对time进行排序,但我试了下,发现并没有成功。感觉支持的不是很好,可能是我没有用好。

2、对于时间,如何要使用event time,那么在前面的datastream先注册好,然后在注册table的时候,在对应的属性后  .rowTime,这样就表示这个是event time了。如果用的是processingTime,那么就需要在注册表的时候,属性那里,增加一个proctime.proctime,这个时候proctime就是系统当前时间,可以直接拿来用。

对于其他的知识点的话,大家可以多看看官网

https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/table/sql.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flink SQL 实战是一个常见的应用场景,可以用于数据处理和分析。下面是一个简单的 Flink SQL 实战示例: 假设你有一个包含用户购买记录的订单表,包括用户ID、购买时间、商品ID和购买数量等字段。你想通过 Flink SQL 来计算每个用户的总购买金额。 首先,你需要将订单表注册为一个 Flink 的表。你可以使用类似下面的代码来实现: ```java StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env); // 创建一个DataStream,读取订单数据 DataStream<Order> orderStream = env.addSource(new OrderSource()); // 注册DataStream为一个表 tableEnv.createTemporaryView("orders", orderStream, "userId, purchaseTime, productId, quantity"); ``` 接下来,你可以使用 Flink SQL 来查询每个用户的总购买金额。可以使用类似下面的代码: ```java // 执行SQL查询,计算每个用户的总购买金额 Table result = tableEnv.sqlQuery("SELECT userId, SUM(quantity) as totalPurchaseAmount " + "FROM orders " + "GROUP BY userId"); // 将结果转换为DataStream输出 DataStream<Result> resultStream = tableEnv.toAppendStream(result, Result.class); // 输出结果 resultStream.print(); ``` 在上面的代码中,我们使用了 Flink SQL 的聚合函数 SUM 和 GROUP BY 来计算每个用户的总购买金额。最后,将结果转换为 DataStream 并打印出来。 这只是一个简单的实例,实际的 Flink SQL 实战涉及到更复杂的查询和处理逻辑。你可以根据具体的业务需求,使用 Flink SQL 来实现更多的数据处理和分析任务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值