项目说明

日志收集模块

  1. 运行gmall0311-logger项目下的Gmall0311LoggerApplication,启动web服务收集上传过来的日志并存进kafka中
  2. 运行gmall0311-mock项目下的JsonMocker,模拟app应用上传日志到web端
  3. 查看kafka,可以看到数据已保存到kafka

实时预警

根据日志数据中的系统报错异常,或者用户行为异常检测,产生预警日志并图形化展示

需求:同一设备,5分钟内三次及以上用不同账号登录并领取优惠劵,并且在登录到领劵过程中没有浏览商品。达到以上要求则产生一条预警日志。

val sparkConf: SparkConf = new SparkConf().setAppName("alert_app").setMaster("local[*]")

      val ssc =new StreamingContext(sparkConf,Seconds(5))

      val inputDstream: InputDStream[ConsumerRecord[String, String]] = MyKafkaUtil.getKafkaStream(GmallConstants.KAFKA_TOPIC_EVENT,ssc)

    val eventInfoDstream: DStream[EventInfo] = inputDstream.map { record =>
      val eventInfo: EventInfo = JSON.parseObject(record.value(), classOf[EventInfo])
      eventInfo

    }

    eventInfoDstream.cache()
    //    1 ) 5分钟内 --> 窗口大小  window      窗口 (窗口大小,滑动步长 )   窗口大小 数据的统计范围    滑动步长 统计频率

    val eventWindowDStream: DStream[EventInfo] = eventInfoDstream.window(Seconds(300),Seconds(5))
    //    2) 同一设备   groupby  mid
    val groupbyMidDstream: DStream[(String, Iterable[EventInfo])] = eventWindowDStream.map(eventInfo=>(eventInfo.mid,eventInfo)).groupByKey()
    //    3 ) 用三次及以上不同账号登录并领取优惠劵     没有 浏览商品
    //    map   变换结构 (预警结构)   经过判断  把是否满足预警条件的mid 打上标签
    val checkedDstream: DStream[(Boolean, AlertInfo)] = groupbyMidDstream.map { case (mid, eventInfoItr) =>
      val couponUidSet = new util.HashSet[String]()
      val itemsSet = new util.HashSet[String]()
      val eventList = new util.ArrayList[String]()
      var hasClickItem = false
      breakable(
        for (eventInfo: EventInfo <- eventInfoItr) {
          eventList.add(eventInfo.evid) //收集mid的所有操作事件
          if (eventInfo.evid == "coupon") {
            //点击购物券时 涉及登录账号
            couponUidSet.add(eventInfo.uid)
            itemsSet.add(eventInfo.itemid) //收集领取购物券的商品
          }
          if (eventInfo.evid == "clickItem") { //点击商品
            hasClickItem = true
            break() //如果有点击 直接退出
          }
        }
      )

      //判断 符合预警的条件    1)  点击购物券时 涉及登录账号 >=3   2) events not contain  clickItem

      (couponUidSet.size >= 3 && !hasClickItem, AlertInfo(mid, couponUidSet, itemsSet, eventList, System.currentTimeMillis())) //(是否符合条件 ,日志信息)
    }

      val alterDstream: DStream[AlertInfo] = checkedDstream.filter(_._1).map(_._2)


    // 保存到ES中
......

采集架构图

在windows中实现案例Spark实时交易数据统计_spark


spark streaming实时统计日志中的信息并输出到es中,最终由kibana展示

实时计算

T+1模式

在windows中实现案例Spark实时交易数据统计_数据_02

  1. 利用sqoop从业务数据库中批量抽取数据
  2. 利用数仓作业,在dws层组织宽表(用户购买行为)
  3. 开发spark的批处理任务,把dws层的宽表导入es中
  4. 从es中读取数据并显示到可视化界面

优点是能利用离线处理好的dws层宽表,直接导出一份到es进行快速交互的分析,但时效性等同于离线数据

在windows中实现案例Spark实时交易数据统计_spark_03

T+0模式

在windows中实现案例Spark实时交易数据统计_数据_04

  1. 利用canal抓取对应数据表的实时新增变化数据,推送到kafka
  2. 在spark-streaming中进行转换、过滤,关联组合成宽表的结构
  3. 保存到es中,读取es数据并展示到可视化界面中

在windows中实现案例Spark实时交易数据统计_spark_05

此时会产生双流join

在windows中实现案例Spark实时交易数据统计_数据_06


双流join即订单的数据来了,但订单项的数据还没过来,或者订单项数据过来了,但订单表的数据没过来。两者之间无法直接关联双流join的解决方案:如果另一方数据没有过来,则缓存这一方的数据,查询的时候如果stream里面没有相应的数据,就继续查询缓存里面是否有匹配的数据

在windows中实现案例Spark实时交易数据统计_kafka_07

canal:分布式数据同步中间件
canal是基于数据库增量日志解析,提供增量数据订阅和消费

场景1:更新缓存

在windows中实现案例Spark实时交易数据统计_spark_08


场景2:抓取业务数据新增变化表,用于制作拉链表


场景3:抓取业务数据新增变化数据,用于制作实时统计

phoniex是hbase的开源sql皮肤,可使用jdbc api开代替hbase客户端api来创建表、插入数据和查询hbase
本项目中sparkstreaming从kafka中拉取数据保存到hbase中都使用了phoniex,便于后面直接使用sql语句来统计查询