从计费出账加速的设计谈周期性业务的优化思考
1 号恐惧症
你有没有这样的做 IT 的朋友?年纪轻轻,就头发花白或者秃顶,然后每个月周期性的精神不振,一到月底,就有明显的焦虑。如果有,他可能就是运营商行业做计费运营的,请对他好点,特别是在国庆、元旦这种节日,尽量少晒些美食啊、旅游啊这类的照片,否则,他真的可能拉黑你。
为什么这群人会如此恐惧 1 号呢?因为 1 号,是运营商计费出账的日子。这个日子,要持续 N 个小时的紧张劳动,神经绷紧,谨防数据库突然宕机,焦虑程序任务能啥时候跑完,跑的结果对不对。总之,直到做完回去睡觉,都可能会被噩梦惊醒。
周期性业务场景普遍存在,比如会员月度结算、薪酬月度发放,以及林林总总的月度报表等,周期性是生活中的惯性规律。那么有没有办法给这些周期性业务优化减负呢?
原因分析
当然有。
运营商计费系统 1 号要做的事情,就是批价出账。所谓出账,其实就是生成用户账单的过程。对于正常使用的用户,出完账后,可以查看和打印上个月的消费账单,余额不足的用户,为了防止继续欠费会被停机需要尽快缴费;出账生成的数据,要供财务、经营分析、结算等多个部门使用。
可以看出,出账事关用户感知,事关企业运营,非常重要。出账也需要极高的准确性,不说百分百,但是 99.999%还是要做到的,还需要极高的及时性,因为其他部门的同事都等着你的米下锅呢。
可能有同学要问:运营商行业信息化建设那么早,难道还不成熟?怎么出账出的还如此纠结呢?
先说答案。究其根本,还是日益增长的业务量与落后的业务流程之间的矛盾。计费的基本业务流程、数据模型大概在十几年前就基本确定,后面持续在提升,也只是修修补补,没有太大的变化。当然,即使是站在今天的角度,这个模型和流程依然是十分的灵活而且优秀(以十多年没有大的修改就可以看出),但是也存在不适应现在业务的落后的地方。
这个业务流程哪些地方落后呢?
可能对于大部分人,你的手机费用无非就是套餐费+超出套餐的费用,月初收你一笔费用,然后每天实时根据清单算出超出的费用,没啥难算的。但是站在计费人员的角度,还有一些人,他们的费用是某些账目的费用打个折,然后某些加起来保个底,再封顶之类,个人的算完,还要把这些人集合成一个单位,再算一次。
这些业务现在看来十分特殊,但是在十几二十年前,手机还没广泛使用的时候,其实是固定电话的主流业务(也基于硬件情况,甚至连基于套餐的清单优惠都实现不了),这部分用户,不仅固定的费用,是月底才计算(固定费用计算流程),在月底,在完成了所有话单费用的计算之后,还要加上个人的账单优惠流程(用户级优惠)、家庭或单位的账单优惠流程(账户级优惠),甚至还有些杂在一起的其他的优惠(捆绑优惠),而且更加过分的是,这些都只能串行,因为一个费用会影响另一个费用,这个流程计算固定费用的部分,我们称之为租费计算流程,后面的几个优惠,我们称之为账单优惠流程。
这种业务作为主流其实持续了近十年左右,而新的业务也在不停的增长,直到新的业务变成主流。而老的业务也没法去抛弃,这就造成了系统中存在不少的这种用户需要去“特殊处理”(下文会称这些用户为特殊用户),老的业务流程就一直保留了下来。另外一方面,这近十年,用户量增长了十倍的数量级,业务量增长了百倍的数量级。因为业务量的增长,这些业务流程处理时间越来越长(从 10 个里面挑 5 个和从 100 个里面挑 5 个的效率肯定不一样)。虽然硬件水平在增长,程序也一直在优化,但是得到的效果不能说毫无作用吧,也只能说九牛一毛。
嗯,相信原因已经说清楚,主要还是业务流程的问题。业务在增长,业务的模式也在不停的更新,而业务流程既要适应老的业务,也要适应新的业务。新的业务因为是后来者,所以是在很多都是老的业务流程上打的补丁,虽然满足了业务需要,但是也不能避免的造成了新的系统负担。
那接下来要做的事情就是业务流程的优化了。
整体业务流程的优化
先说一个“错误”答案。
你可能首先想到的,既然老业务流程的用户挑出来慢,那是否可以把这部分用户单独存放,然后在月底对这些用户单独处理呢?不是不行,但是得不偿失。这主要是两个方面的原因,其一,这样涉及的流程改造点太多,从受理、到批价、到最后出账都需要大刀阔斧的改造。另外,部分资费不仅仅包含这部分特殊用户,也包含主流的用户,“融合”是个更大的问题【相信知道预后融合(本地电信套餐类型)这个词的朋友都知道】 其二,即使这么改造了,其实月底仍然要走完原来的流程,虽然会快,但是也不见得能快多少。
我们其实做了一个更加大胆的决定,那就是,在月底的时候,彻底抛弃租费计算流程、账单优惠流程。
通过分析,在包括前文所说的特殊用户在内,其实在月底账单优惠前,95%的用户每月费用不变,仅存在固定费(或者说套餐内费用),只有 5%的用户费用发生变更,也就是说会产生超出套餐包含量的计量费。也就是说,因为账单优惠触发的量并不多,我们完全可以在月初的时候,租费以及相关的账单优惠全部预生成出来,然后再计算每天超出的计量费。产生一笔,我们计算一次优惠,这样到了月底,就可以直接不再计算账单优惠了,改造完成后,计费的整体流程如下图:
月底需要做的核心事情,就是图的最下面橙色框的内容,一般只需要 1.5 小时就可以完成,原来一直要到第二天早上 8 点才能结束的出账核心流程,在 2 点一般就可以结束了。
看到这里,你自然会有点认为,这其实还是没抛弃以前的业务模式,也只是在原有的流程上打补丁而已(或者说重新组合),关于这个疑问,我们的理解是,补丁完全可以打,就看打的漂亮不漂亮了。
漂亮还是不漂亮,我们认为应该是有三个标准。
✨ 第一个标准,也是最重要的标准,是有没有影响最终用户的感知。整体业务流程修改后,由于能够更加实时和精准对用户的费用进行判断,催缴、停复机等动作更加及时。最终用户的感知不仅没有影响,反而是优化了,所以是满足的。
✨ 第二个标准,使用系统本身和下游系统的用户的需求是否满足。整体业务流程修改后,加快了出账的速度,当然是满足的。其实除了出账快以外,还抛弃了一个每月 25 日左右的“预出账”流程,原来做这个流程的目的,一个是为了防止月底出账有大的波动的时候,核查措手不及;另外一个方面,也是尽可能早给下游系统如经营分析系统一些分析的数据。这样改造后,每天都可以核查预期月账的情况,也可以每天都提供下游系统基本准确的数据,这样就可以抛弃掉这个预出账流程,也增加了下游系统分析的准确性。
✨ 第三个标准,是否能尽可能兼容以前的流程。实际上,本次的改造,可以理解为积木的重新组合,对部分组件进行了适配性修改。如果发现问题,还是可以重新搭回以前的流程,实际上,这次改造是否升级都可以用配置开关来实现。实际实施中,各地也存在一些不适配新流程的出账流程,这部分完全保留,也没有问题。
当然,虽然业务流程确实没有伤筋动骨,但是也不是看上去的那么简单。
核心流程改造:租费与优惠
从前文流程可以看到,首先要做的是,把所有用户的租费和优惠在月初先算出来,按天计算后放入中间表,那就是增加月初的租费、优惠预生成流程。
先说简单一点的租费。
在优化之前,租费的计算,周期有三种类型,即月初、每日(日租)、和月底,现在其实要做的,就是把月底的租费计算提前到月初,并考虑用户感知,将租费摊分到每日。实际设计时,我们认为可以直接把所有用户的租费(包括日租)都放在月初执行,直接生成每天的数据,都放入中间表中,后面增加一个中间表到账单表的流程,实现每日的“账单合并”(合账流程)。
这样的话,租费的计算周期,其实就变成了一种类型,都是月初计算,只不过按照原月初、每日和月底的不同的一些业务差别,每天计算的逻辑不太一样而已(比如月初计算的都在 1 号收费)。
至于优惠就复杂一些。流程上,与租费还是一样的,都是分散到每天,然后再每日抽取合账,主要还是在于优惠的摊分计算方式非常复杂,以下就举两个例子(非计费专业同学可以只感受一下):
赠送固定值的计算方法
需要记录优惠配置的赠送固定值 X。
若 charge1+…+chargeN-X<=0,则优惠费用为直接对当天费用取负值;若 charge1+…+chargeN-X>0 并且 charge1+…+charge(N-1)-X<=0,则当天的优惠的总费用为 charge1+…+charge(N-1)-X,以后每天的优惠费用都为 0。
封顶的计算方法
需要记录优惠配置的封顶值 X。
若 charge1+…+chargeN-X<=0,则第 N 天优惠费用为 0;charge1+…+chargeN-X>0,则第 N 天优惠费用为 X-(charge1+…+chargeN),第 N 天以后为-charge(N+1)…-charge31。
当然,对于优惠,实际更加需要关心的是,如何做实时的优惠。
第一个问题就是,何时该触发实时优惠?
首先,费用变动肯定需要触发实时优惠流程。这部分我们设计之初,认为可能会存在效率问题,因为所有优惠都需要重算,所以触发的账目为优惠参考的账目组中的账目,但是后面实际测试,实际上每一次实时优惠,即使所有优惠都进行重算,响应基本为毫秒级,且按照批次而非按照清单触发后,触发的次数并不多。所以现在通用的做法是,所有产生的超出费用都会触发优惠的重新计算(可配置),也避免因优惠的各种参考科目问题造成出现费用计算错误的情况。
其次,用户资料的变动需要触发实时优惠流程。用户资料的变动是指用户订购了新的套餐、退出或者加入了某个需要参与优惠的账户或者其他优惠对象等等变动。这种情况下,其实也不是所有的变动都需要触发(比如新套餐为次月生效),还是要进行一些筛选。不过肯定有聪明的同学会立刻觉察到另外一个问题:现在的套餐下,很多都不是一个人的套餐,有些与家庭有关,有些与公司有关,那一个用户的变动,是否需要触发所有人的优惠重算呢?
如果你想到了这个问题,请允许我为你鼓掌。
这就是我们要说的第二个问题:单个用户的费用变动,哪些关联用户要触发实时优惠?又怎么样把这个用户关联的其他用户找出来呢?
关联用户分组以及配套流程改造
熟悉三户模型的朋友知道运营商用户资料实际是用户、账户、客户的三层关系,加上费用计算的套餐(销售品)关系,比较常用的就是这三个关联:套餐关联、账户关联、客户关联。其实还有一些比较随意的捆绑关联,这这些是极少数,可以保留原有流程,单独处理。这几个关联关系比较麻烦的,是这三个关联关系,存在多层的嵌套关联,而某些用户因为有些大账户的存在,会关联数万级别的用户分组,处理会比较慢。
所以,这个关联关系,肯定要先生成出来,而不能是到了相应的触发流程,再去寻找。我们在用户资料层面,引入了关联用户分组这个模型,与之配套的,需要修改一些流程。
首先是生成这个关联用户分组的资料接口。
在实施的时候,参考目前的现有资料,将关联用户分组先生成出来,然后进行用户资料接口的配套改造,根据用户的受理情况,进行一个实时的分组判断和处理,对用户所在的关联分组进行维护。
这样的话,就做到了当某个用户费用变动时,将其关联的其他用户也再触发一次实时优惠。当然这里面存在一些过滤的问题,因为业务规则比较复杂,篇幅有限,这里就不详细描述。
其次是批价流程。
批价流程,最好也根据用户关联分组来区分进程,这么做的好处,其一为了现在引入的分布式计算引入的流框的效率,其二是关联分组肯定会包含套餐关联的用户,处理累积量时,可以尽可能少的遇到累积量并发锁问题,批价效率也自然会提高。当然,批价流程进行改造的前提,前面的预处理流程将“用户关联分组属性”填出来。
还有一点就是优惠对特别大的分组的处理的大账户优惠,进程上需要分开,避免造成处理慢影响其他用户,程序上也需要优化,不过这也是“过于先进,不便展示”的内容,只说一点成果,这个优化之后,我们的大账户处理做到了秒级响应。
当然,各种需要改造的小流程还是挺多,比如话单回退、重处理、补退费等等,这些就不一一赘述了。
画龙点睛:出账流程自动化
虽然是一个保守而传统的计费人,但其实我们非常符合电影里面程序员或者黑客的形象:噼噼啪啦敲一阵键盘,然后得到一个结果,然后想半天,又噼里啪啦敲了一阵键盘,如此往复,直到自己的任务完成。但是这个辛苦,只有自己才能感觉到,除了减少流程、缩短时长,谁不想做到自动化呢?
既然都做到实时的出账了,那为啥不做的更彻底呢?
所以,这次的改造,除了流程的优化以外,我们还做了系统自动化调度、实时可视化展示、智能化的支撑等等。完全摆脱过去人工值守,人工启停应用的低效率处理模式,完全提升了出账效率。
以下是一张成果图,是领导千叮咛万嘱咐让我放进去的,当然,相信你看完这张图,就知道我们做了啥了(别问,问就是过于先进)。
总结:打破常规、实事求是
运营商计费系统是非常传统的 IT 系统。系统模型、业务流程的基本面,已经运行了 20 来年。在这 20 来年中,业务模式在不停更新,业务本身在不停发展,而系统需要满足各个时期的业务,这就造成了系统中存在很多甜蜜的历史负担。要解决这些负担,即需要有打破常规的勇气,也需要有实事求是的态度,来正确对待我们面临的问题。根据解决的问题和带来的影响来评估,方法是大刀阔斧,还是庖丁解牛(或是中间态)。
大刀阔斧可能迅速且能够解决更多的问题,但是可能影响不可承受;庖丁解牛可能辛苦,但是好在影响面小,出现错误还可以回溯。
我们选择了庖丁解牛式的解决,将周期性业务切的更细,以月末的集中处理,分散到每天处理,并加上相应的自动化以及监控,使处理更加放心。当然这个过程也确实非常辛苦,从主流程优化到配套流程改造,设计的每个点都要详细评估;从设计、开发到实施,每一步都做到精细而且精准。
版权声明: 本文为 InfoQ 作者【鲸品堂】的原创文章。
原文链接:【http://xie.infoq.cn/article/53054d307ca5f9a7b70181c7d】。文章转载请联系作者。
评论