flink实时项目电商用户行为分析(4)---实时流量统计之UV统计之timeWindowAll实现

目录

1.知识点

2.业务目标

3.流程心法

4.模块详解

4.1 创建输入输出样例类

4.2 主object实现

4.2.1 创建执行环境并添加数据源

4.2.2 Datastream map转换为输入样例类

4.2.3 处理逻辑(1)----filter类型,timeWindowAll

4.2.4 处理逻辑(2)----AllWindowFunction实现UV去重

4.3 完整代码

1.知识点

  • scala样例类
  • source api: readTextFile
  • DataStream.timeWindowAll的使用(比较KeyedStream.timeWindow)

     windowAll,不能设置并行度,并行度1;window ,可设置并行度,返回AllWindowedStream

        timeWindowAll,并行度为1,返回AllWindowedStream

        AllWindowedStream.apply(AllWindowFunction),返回DataStream

  

  •  AllWindowedStream.apply 传入全窗口函数AllWindowFunction
    的使用
  • AllWindowFunction的案例

2.业务目标

滚动输出最近1小时内的PV.

窗口:1小时

指标:点击量

3.流程心法

总体流程:创建输入、输出样例类---->主Object

主object: 

1) 创建执行环境,设置并行度、时间语义(事件时间)等参数

2)  transform map转换输入样例类,有序数据设置watermark,无序数据根据乱序时间设置watermark

3)不分组,直接timeWindowAll计算(无法并行)

4)传入UV全窗口函数

5)UV简单全窗口函数实现原理:

      定义一个set类型,直接往里放userid,不用比对了,自动count值

4.模块详解

4.1 创建输入输出样例类

//定义输入样例类
case class UserBehavior(userId: Long, itemId: Long, categoryId: Int, behavior: String, timestamp: Long)

// 定义输出Uv统计样例类
case class UvCount(windowEnd: Long, count: Long)

4.2 主object实现

4.2.1 创建执行环境并添加数据源

val env = StreamExecutionEnvironment.getExecutionEnvironment
    env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
    env.setParallelism(6)

4.2.2 Datastream map转换为输入样例类

// 从文件中读取数据,获取resources中的文件,相对路径
    val resource = getClass.getResource("/UserBehavior.csv")
    print(resource.getPath)
    val inputStream: DataStream[String] = env.readTextFile(resource.getPath)

    // 转换成样例类类型并提取时间戳和watermark
    val dataStream: DataStream[UserBehavior] = inputStream
      .map(data => {
        val arr = data.split(",")
        UserBehavior(arr(0).toLong, arr(1).toLong, arr(2).toInt, arr(3), arr(4).toLong)
      })   //No implicits found for parameter evidence$8:,需要引入 createTypeInformation,或者直接引入import org.apache.flink.streaming.api.scala._
      .assignAscendingTimestamps(_.timestamp * 1000L)

4.2.3 处理逻辑(1)----filter类型,timeWindowAll

val uvStream = dataStream
      .filter(_.behavior == "pv")
      .timeWindowAll( Time.hours(1) )   // 直接不分组,基于DataStream开1小时滚动窗口
      .apply( new UvCountResult() )  //apply传入全窗口函数

4.2.4 处理逻辑(2)----AllWindowFunction实现UV去重

自定义个全窗口函数,用一个set结构保存所有userid

缺点是:1)全窗口 2)SET. 数据量大很容易溢出

// 自定义实现全窗口函数,用一个Set结构来保存所有的userId,进行自动去重。 1)全窗口 2)set,数据量大直接溢出了,那么如何优化呢?  布隆过滤器
class UvCountResult() extends AllWindowFunction[UserBehavior, UvCount, TimeWindow]{

  override def apply(window: TimeWindow, input: Iterable[UserBehavior], out: Collector[UvCount]): Unit = {
    //最简单的思路,定义一个set 类型,直接去重,不用比对了,自动count值
    var userIdSet = Set[Long]()
    //遍历全窗口的所有数据,把userId添加到set中,自动去重
    for(userBehavior <- input ){
      userIdSet += userBehavior.userId
    }

    out.collect(UvCount(window.getEnd,userIdSet.size))
  }



}

4.3 完整代码

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值