# 《并发设计模式》第53章-流水线模式-统计个交易额也能这么慢?

作者:冰河
星球:http://m6z.cn/6aeFbs (opens new window)
博客:https://binghe.gitcode.host (opens new window)
文章汇总:https://binghe.gitcode.host/md/all/all.html (opens new window)
源码获取地址:https://t.zsxq.com/0dhvFs5oR (opens new window)

沉淀,成长,突破,帮助他人,成就自我。

  • 本章难度:★★☆☆☆
  • 本章重点:了解流水线模式的核心原理与使用场景,初步掌握流水线模式的应用场景,能够初步结合自身项目实际场景思考如何将流水线模式灵活应用到自身实际项目中。

大家好,我是冰河~~

在电商业务场景中,往往会存在一个秒杀业务场景,像每年的双11和618等,天猫等国内头部电商平台都会举办秒杀大促活动,在前几年的秒杀大促活动中,这些头部电商平台都会实时统计交易额并展示到交易大屏,那这些交易额是如何实时统计出来的呢?

# 一、故事背景

这天,小菜又接到一个新的需求,就是为社区电商系统增加一个实时统计交易额的功能。从业务需求的角度来看,这个功能是很简单的,就是实时统计日志中每笔订单的金额,对每笔订单的金额进行累加统计,最终得出统计的结果数据。

业务需求很简单,于是小菜也没想那么多,做了简单的分析后,便开始写代码实现功能,没一会儿,就写完代码提交测了。随后便收到测试同事发来的测试报告——性能太差,通不过!

小菜看到这个测试结果,也是一脸差异,这没啥业务难度啊?又是性能差?从代码实现角度来看没啥可调优的了啊!怎么会性能差呢?这次,让小菜排查和定位问题的话,小菜觉得代码逻辑非常简单,自己是没有办法优化代码的性能了。于是,小菜决定还是请教老王,看看老王能不能从业务和功能角度给出一些优化的建议。

这不问不要紧,一问还真是代码性能太差了,不过这不只是从代码角度分析的,从业务角度分析的话,其实可以使用一种新的设计模式,也就是流水线模式来优化统计性能。

# 二、案例分析

小菜所在的公司为了准备新的一年的双11,准备在社区电商系统中新增一个实时统计交易额的功能,并将实时统计的交易额展示到交易大屏。在社区电商系统中,用户每成功下单并成功支付金额后,社区电商系统就会在日志文件中输出一条日志,记录订单的编号和当前订单的金额,只要在实时统计交易额的服务中,实时获取到这些日志信息,进行累加统计,得出结果数据,再实时推送到交易大屏即可,整体流程如图53-1所示。


可以看到,当用户成功下单并支付后,社区电商系统就会记录交易的日志信息,日志信息中会记录订单的编号和订单的金额。实时分析统计服务会实时收集日志并进行分析和统计,最总会将统计的结果数据实时推送到交易大屏。

# 三、案例重现

为了更好的重现问题,这里我们模拟实现实时统计社区电商系统交易总额的功能,具体的实现步骤如下所示。

(1)实现AnalysisService接口

AnalysisService接口是模拟实时分析统计交易总额的接口,定义了一个analysis()方法。

源码详见:io.binghe.concurrent.design.pipeline.wrong.AnalysisService。

public interface AnalysisService {
    Long analysis(List<String> input);
}
1
2
3

可以看到,在AnalysisService接口中定义了一个analysis()方法,输入一个List集合模拟输入的日志信息,返回一个Long类型的结果数据,作为统计出的结果数据。

(2)实现AnalysisServiceImpl类

AnalysisServiceImpl类是AnalysisService接口的实现类,主要是实现了AnalysisService接口中定义的analysis()方法。

源码详见:io.binghe.concurrent.design.pipeline.wrong.AnalysisServiceImpl。

public class AnalysisServiceImpl implements AnalysisService {
    @Override
    public Long analysis(List<String> input) {
        long sum = 0;
        if (input == null || input.isEmpty()){
            return sum;
        }
        for (String i : input){
            String[] arr = i.split("-");
            sum += Long.parseLong(arr[1]);
        }
        return sum;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

可以看到,在AnalysisServiceImpl类中实现的analysis()方法中,遍历输入的List集合,对每个元素使用横线进行分割,并将分割后的数组的第2个元素转换成Long类型,进行累加统计,最终返回统计出的结果数据。

由AnalysisServiceImpl类实现的analysis()方法还可以看出,日志的格式如下所示。

# 查看全文

加入冰河技术 (opens new window)知识星球,解锁完整技术文章与完整代码