Skip to content

Latest commit

 

History

History
83 lines (65 loc) · 3.24 KB

4.5 用户访问Session分析 - 重构Session聚合.md

File metadata and controls

83 lines (65 loc) · 3.24 KB

4.5 用户访问Session分析 - 重构Session聚合

重构前的实现思路

  1. actionRDD做映射成<sessionid,Row>格式
  2. 按Sessionid聚合,计算出每个Session的访问时长和访问步长
  3. 遍历新生成的RDD,将每个Session的访问时长和访问步长去更新自定义Accumulator中自定义的值
  4. 使用自定义Accumulator中的统计值,去计算各个区间的比例
  5. 将最后计算出来的结果写入MySQL对应的表中
存在的问题
  1. actionRDD在之前Session聚合的时候已经映射过,这里显得多余。
  2. 将最后计算出来的结果写入MySQL对应的表中

优点: 解耦,易维护,重代码设计

缺点: 性能稍低

重构后的思路

  1. 不要去生成新的RDD(可能要处理上亿的数据)
  2. 不要去单独遍历一遍Session的数据(处理上千万的数据)
  3. 可以在进行Session聚合时,就直接计算出每个Session的访问时长和访问步长
  4. 在进行过滤的时候,本来就要遍历所有的聚合Session信息,此时,就可以在某个Session通过筛选条件后,将其访问时长和访问步长累加到自定义Accumulator上
  5. 在这两种截然不同的实现方式上,面对上亿,上千万数据时,甚至可以节省时间长达半小时甚至几小时

优点: 性能好

缺点: 高度耦合,代码不易维护

开发Spark大型项目的经验准则:

  1. 尽量少生成RDD
  2. 尽量少对RDD进行算子操作,如果有可能,尽量在一个算子里面,实现多个算子功能
  3. 尽量少对RDD进行shuffle算子操作,groupByKey,sortByKey,reduceByKey,shuffle操作会导致大量磁盘读写,导致严重性能下降
  4. shuffle算子很容易导致数据倾斜,一旦倾斜,就是性能杀手
  5. 无论什么功能,性能第一

重构代码实现

在聚合过程中直接计算起始时间和结束时间,并计算步长

具体细节看源码

JavaPairRDD<Long,String>  sessionId2PartAggrInfoRDD = sessionId2ActionsRDD.mapToPair(t -> {
    //Session起始时间
    Date startTime = null;
    Date endTime = null;
    //Session访问步长
    int stepLength = 0;
    
    //遍历session所有用户行为
    while (iterator.hasNext()) {
        //计算Session开始和结束时间
        Date actionTime = DateUtils.parseTime(row.getString(4));
        if (startTime == null) {
            startTime = actionTime;
        }
        if (endTime == null) {
            endTime = actionTime;
        }
        if (actionTime.before(startTime)) {
            startTime = actionTime;
        }
        if (actionTime.after(endTime)) {
            endTime = actionTime;
        }
        //计算访问步长
        stepLength++;
    }
    //计算Session访问时长,单位:秒
	long visitLength = (endTime.getTime() - startTime.getTime()) / 1000;
    //聚合数据拼接:key=value|key=value
    String partAggrInfo = Constants.FIELD_SESSION_ID+"="+sessionId+"|"
        +Constants.FIELD_SEARCH_KEYWORDS+"="+searchKeyWords+"|"
        +Constants.FIELD_CLICK_CATEGORY_IDS+"="+clickCategoryIds+"|"
        //重构添加新字段:访问时长和访问步长
        +Constants.FIELD_VISIT_LENGTH+"="+visitLength+"|"
        +Constants.FIELD_STEP_LENGTH+"="+stepLength;