批量源数据按时间分片聚合

简介
该算法才有类似滑动时间窗口的方式,每笔数据(MergeDataDO)流入后,会根据key1,key2判断是否是新数据或者已被计算过的数据,新数据则需要构造计算结果存储对象(MergeCalcResultDO),已被计算过的key则直接取出,继续进行聚合运算
public class MergeCalcuService {
    //聚合数据临时存放cache
    @Resource
    private MergeCacheService cacheService;
     /**
     * 处理聚合计算
     * @param mergeDataDO 传入数据模型
     * @return
     */
    public MergeCalcResultDO calMergeData(MergeDataDO mergeDataDO) {
         //承载每笔聚合返回结果
        MergeCalcResultDO mergeCalcResultDO = null;
        String key4GroupBy = mergeDataDO.getKey4GroupBy();
        String key1 = "M1_" + key4GroupBy;
        String key2 = "M2_" + key4GroupBy;
        //查看是否是已被计算过的数据,便于按照时间点滚动运算
        MergeCalcResultDO C1 = cacheService.get(key1);
        MergeCalcResultDO C2 = cacheService.get(key2);
        if (C1 == null || C2 == null) {
            C1 = createCalc(mergeDataDO, 0);
            C2 = createCalc(mergeDataDO, 1);
            cacheService.put(key1, C1);
            cacheService.put(key2, C2);
        }

        long time1, time2, time3, time4;
        //分槽时间点扁平聚合到整点(10:01:35->10:01:00)
        time1 = C1.getFirstTime();
        time2 = C2.getFirstTime();
        time3 = time2 + C2.getInterval() * 1000;
        time4 = time3 + C2.getInterval() * 1000;

        long nowtime = mergeDataDO.getCurrTime();

        if (nowtime < time1) {
            // 过期数据丢弃
        } else if (nowtime >= time1 && nowtime < time2) {
            // 计算在第一槽的数据
            calcModule(mergeDataDO, C1);
            // 若第一槽满
            if (C1.isFull()) {
                // 返回第一槽的数据,把第二槽移到第一,新建一个第二槽.
                MergeCalcResultDO tmpCalc = createCalc(mergeDataDO, 2);
                mergeCalcResultDO = C1;
                C1 = C2;
                C2 = tmpCalc;
                cacheService.put(key1, C1);
                cacheService.put(key2, C2);
            }
        } else if (nowtime >= time2 && nowtime < time3) {
            // 计算在第二槽的数据
            calcModule(mergeDataDO, C2);
            // 若第一槽满
            if (C1.isFull()) {
                // 返回第一槽的数据,把第二槽移到第一,新建一个第二槽.
                MergeCalcResultDO tmpCalc = createCalc(mergeDataDO, 1);
                mergeCalcResultDO = C1;
                C1 = C2;
                C2 = tmpCalc;
                cacheService.put(key1, C1);
                cacheService.put(key2, C2);
            }
        } else if (nowtime >= time3 && nowtime < time4) {
            // 若第一槽数据不满,当第时间点落到三槽的数据流入,强制将第一槽数据返回
            // 返回第一槽的数据,把第二槽移到第一,新建一个第二槽.
            MergeCalcResultDO tmpCalc = createCalc(mergeDataDO, 0);
            mergeCalcResultDO = C1;
            C1 = C2;
            C2 = tmpCalc;
            cacheService.put(key1, C1);
            cacheService.put(key2, C2);
            // 在新的第二槽继续计算
            calcModule(mergeDataDO, C2);
        } else {
            // 新来的数据完全超出范围(可能是停止了一段时间)
            // 全部清零,重新开始
            C1 = createCalc(mergeDataDO, 0);
            C2 = createCalc(mergeDataDO, 1);
            cacheService.put(key1, C1);
            cacheService.put(key2, C2);
            // 在第一槽的数据
            calcModule(mergeDataDO, C1);
        }
        return mergeCalcResultDO;
    }

图解

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值