签收率系统试运营以来,每天算出高额罚款,虽然没有真正执行,但也挺吓人的。并且,完完全全的把全网人员积极性提升起来了。
总部网络管理中心每天给出各省区前一天的签收率报表,来了个排名和点名;
各省区管理中心给出本区域大网点的签收率报表,也来了个排名和点名;
大网点把超时单号导出(它们导致签收率下降),按承包区和业务员分组排名;
排行榜这一招,在中国几千年以来的各行各业,真的是屡试不爽。甭管是为了降低罚款还是为了面子,所有人都跟打了鸡血一般。
各层级领导和管理人员拿着数据说话,更是理直气壮。“A网点就在你家隔壁,为什么它的派送比你好那么多”。底下一顿之乎者也,各种解释。此时,管理人员恨不得看着这些业务员派送,为什么那么慢。于是提出,要是能够马上看到网点的派送数据和签收率就好了!
【改架构】
系统架构是每天凌晨计算T-1(前一天)全网的签收率,因为这个时候大部分数据都已经上传完毕。按照日期和网点过滤数据,然后分组聚合,几个小时下来就能计算完。
如果实时计算当天数据,就得修改架构,几个小时才能算一次的办法显然不适用。
离线全量计算需要改为增量计算,否则到了下午晚上,随着当天数据变多,几千个网点要算很久;
业务策略越完善越复杂,最难的在于如何界定每一票件属于哪个网点哪一天的派送任务,只要定好日期、网点和频次(一二三派),那么计算网点今天的签收率最多就是一个分组统计的事情;
把末中心发件数据,派件网点的派件和签收扫描数据等,当作源源不断的数据流,以每秒几百行到几千上万行的速度流入系统。只需要对每一次操作进行增量式处理,即可达到我们的目标。这就是流式计算的思想。
【技术选型】
系统前期采用Oracle存储过程进行数据批量计算,.Net做数据展示。
原计划采用Hadoop替换存储过程来进行离线计算,就此夭折,因其做不到实时增量计算。当时也完全没有人会Spark和Kafka。
同时,业务策略日渐复杂,需要更多外部数据辅助计算,存储过程必然得换掉。
在这个背景下,我们选择了公司内最强的.Net开发技术,自主设计一套增量计算系统。(当时Java占比很低)
参考了多年前的系统经验(只有每月百万级数据),把数据按照入库时间切分为小片,每5秒作为一片,从数据库抽取出来,进行逻辑计算。判定每一票属于哪个网点哪一天的派件任务后,放入签收明细表中,按照省份进行分表。完美的把一个大数据计算系统,转化为大家熟知的数据库类应用系统,充分利用现有的人力资源和技术储备优势。
新架构可以多线程并行计算,并且可以大量利用Redis等众多中间件进行优化。
【系统上线】
系统很快开发完成,试跑数据,每10分钟对明细表跑一次分组聚合更新签收率统计表。末端中心发件以及快递员签收后,签收率的确变了,不过需要等10分钟才会变动。用户不答应了,10分钟不变啊,这不算实时……真没想到,系统上线前夕,还遇到这么个小插曲!
整个系统用了一个Oracle数据库和一台32G内存的计算服务器,按省份分了12张表,保存6个月历史数据,平均每张表2亿多行数据。(当时2016年每天业务量1000万,现在2019年每天业务量4000万)
尽管有分区索引,但对2亿行数据表进行聚合统计,效率是相当低下的,10分钟周期不能缩短。最后用了个很出人意料的办法,给12张明细表加插入触发器,在其中对统计表进行累加更新,最终效果就是,派件量和签收率数据,每秒都在改变,用户非常满意!用触发器会让很多程序员笑话,但它很有效,最重要的是用户很满意,那就足够了!
【业务赋能】
签收率各个指标数据每秒都在跳动,全国各地分公司和数千网点的管理人员,犹如获得了一个派件端的数据大屏。
网点管理者通过积累本网点每个小时点的签收率,比如A网点每天11点签收率应该在70%左右,某天发现快11点了才做到60%,那么底下一定出了问题,马上电话联系沟通;
省分公司早上10点,发现某个网点签收率还不足1%,即怀疑网点是否遇到了困难,或者网点老板跑路?
电商旺季,网点在派车去中心拉件之前,就已经在系统看到了当日应派件量,可以准确地安排车辆和派件人员;
……一个签收率系统,不断向数据链的前后拓展,不断增加各种业务需求,俨然已经成为了派件端数据标杆,远超设计预期。
……闭关十天攻克一个技术问题,也写了十多天的代码,导致《在路上》系列断了十多天,今天恢复。