关于维护结算付款系统的一些经验

17年12月开始维护打车结算系统,至今一年有余矣,些许心得,录于此处,望对后来者有所裨益。

清分、入账不在讨论范围内,此处结算付款只涉及到算钱、付款的流程。

业务特点:

当今社会,凡是和钱相关的,都是大问题。

从这个角度出发,付款系统有三个显著的特点

最直接,离钱最近,无丝毫转圜余地

不同于其他系统,发生错误、事故后,可以后各种补救措施。

订单、红包、风控、计费、导航等系统的错误(绕路,无法支付,算错钱,红包无法使用,长时间打不到车,奖励漏发,惩罚出错),可以采取各种手段安抚,给用户发红包,发代金券,等等等等。

说到底,大多都是间接和钱相关,间接的空间越大,可操作空间就越大,越容易弥补。

再来看看付款:

直接把钱打到用户银行卡,这是离钱最近的地方,其中没有哪怕一点点缓冲的空间,一旦出错,几乎不可挽回。

多发了,基本上就是公司损失了,要回来的概率基本可以忽略。

少发了,还好,被用户骂一通,补发,然后陪个红包啥的。

从这一点看,似乎没那个严重,但是,这里忽略了第二个特点:

数据量,雪崩类型的

订单都是一个一个发生的,一笔一笔发生的,单笔其实没多少,几十块而已。

但是付款,非常不同,那可是一个周期(比如一星期)累积起来的、上百倍的数量级,基本每笔付款都是少则成百,多则上千。

这还不是最恐怖的,最恐怖的是,这个成百上千还要乘一个几十万!

为什么呢?因为钱都是统一时间发出去的,比如每周二给司机们发钱,这一发就是十几万、几十万笔。

举个例子:

一个星期内,周一发现线上问题,报警几十个后,紧急修复上线,影响范围几十个用户,涉及资金几百元。

然后时间来到了周末,开始给司机们发钱了,我勒个去,开始报警了,紧急修复?来不及的。结果影响范围10万司机,涉及资金1亿元。。。

你以为到这里就完了吗?no!

时间敏感度

用户的习惯很容易就会被培养起来,此后一旦有些许改变,必然引来用户的疑问。

仍然举个例子:

平时都是上午10点发钱,因为某些原因(比如钱发不出去了,紧急修复一把,用了1个小时),延迟到11点发钱,那么这1个小时内,必然会有很多客诉。

如此,为之奈何?

解决办法

提醒/报警

不同于其他系统,通过一些离线任务,可以及时发现系统中潜在的bug,然后修复。

付款系统,事后的核对,有用,但是也仅仅是聊胜于无,等你发现问题,黄花菜都凉了。

所以,尽可能的事前报警,如果实在做不到,底线也是事中报警。

事前报警/提醒的方法有以下几种:

  1. 如果上午10点发钱,那么至少在9点钟知道要发多少钱,时间长了,一眼就能看出来这笔钱有没有问题,如果有问题,起码有时间在10点之前修复。
  2. 发邮件?APP报警?都不靠谱的,人不在公司,最简单直接的就是发短信!
  3. 如果哪天改过代码,那么请务必保证在打款日的9点左右能让自己处于一个可以改代码并发布的环境中。
  4. 不要吝啬error日志,但凡可能出问题的地方,请毫不留情的log.error,请务必保证error能触发报警。宁可错杀一千,不可放过一个。

安全第一,性能第二

  1. 写代码时,尽可能简单粗暴,怎么简单怎么来。当然前提是满足上面提到的用户的时间敏感度,毕竟你不能为了追求安全,全部加锁单线程,四五个小时才把10万笔钱发完。。。
  2. 尽可能少的使用一些华而不实的代码上的“技巧”。
  3. 不要吝啬使用锁,分布式锁、CAS锁、数据库悲观锁,等等,只要控制好锁的粒度,这些影响不了太多的性能,但是带来的安全性收益甚大。

如果可能,尽量留出一些可操作的空间

还是那句话,越间接,可操作空间就越大,问题就越来得及弥补。

比如10点发钱,你可以在2点就算出应该发多少钱,然后这期间,都可以用来发现和解决问题的。

事前,事前,事前

请不遗余力,无所不用其极的尽可能让问题在事前暴露出来,流计算,风控,用户画像,数据分析,异常检测等等,能想到的都可以考虑一把。

最后也是最重要的

淡定,无论何时,请淡定,务必保证头脑是清晰的。


因僧问我西来意,我话山居不记年。
草履只栽三个耳,麻衣曾补两番肩。
东庵每见西庵雪,下涧常流上涧泉 。
半夜白云消散后,一轮明月到床前。