浅析银行总分账务核对
文章来源:e路向上,文章仅供个人学习
浅析银行总分账务核对
做过银行涉账系统开发的同学,几乎不可避免要跟“总分核对”几个字打交道,在强调传帮带的银行科技部门,通常岗位导师都会苦口婆心的强调:“’账’一分都不能错”,至于为什么不能错,除了口口相传外,似乎也没有特别硬核的理由。本文尝试回到商业银行账务处理的起始,对总分核对的业务原理、技术本质进行解释,并尝试从银行展业角度,探讨被奉为圭臬的“总分核对”,真的“一分都不能错吗?”
银行账务处理内容与步骤
银行业务操作的本质是资金流动的记录与管理,其核心职能是会计。银行信息化的起点,最早可追溯到“会计电算化”时期–将柜台上手工填写的大量会计传票,及需要手工编制的日计表,纳入系统管理,依靠系统来处理大量账务(处理业务的手段或工具会变,但业务的实质不会变,会计电算化后系统处理的工作与手工账时代并无二致,只是更快、更准确)。会计电算化需要复现的手工处理步骤大致如下:
以一笔客户柜面现金存入为例,手工处理的步骤包括:编制现金存入凭证/传票,然后登记客户分户账,日终的时候,登记科目日结单(对一个会计科目当天发生额和传票张数进行汇总的记录,该例子中是对现金科目和客户存款总账科目涉及的记录数进行处理),根据科目日结单情况,登记科目日计表(借方发生额、贷方发生额,再更新科目余额)。
显而易见,操作过程中有两部分内容需要处理,一是对客户的账–客户账户余额更新,二是银行自己的账–总账或科目账,日终需要将很多传票(或凭证)汇总后,更新总账。这里有两个关键点:1、分户账(即客户账户)的更新依据,是依赖第一步编制的凭证/传票,科目账(总账)的更新依据,同样是第一步编制的凭证/传票;2、总账日计表的更新,依赖日间交易时填写的传票汇总出的借方发生额和贷方发生额轧差。
考虑到商业银行经营的特殊性,保证每一笔交易的准确无误,确保资金交易的准确性与账务的准确性,是银行确保其信用的根本。此时,如果在账务处理时,只更新了分户账,但漏了登记总账,或者登记了总账,而漏了更新分户账,都会导致两边的账对不上,可能造成严重的财务问题或信任危机。(总账与分户账概念,见本号“会计引擎:交易与核算分离的前世今生”一文。),因此,将分户与总账的账务对平,确保没有差错,就变得非常重要,这就是“总分核对”的起源。
总分核对的范围与类型
狭义上的总分核对:即是按字面理解:总账(或科目账)与分户账的核对,因为总账(科目账)与分户1对多的关系(见下图),更准确的表述是:以某日日终(通常为系统日切时点)为线,将已经更新完的,当日按所属不同会计核算科目的分户账余额汇总后,与根据交易日志更新过的科目账余额进行核对,核对结果要求完全一致,否则即为总分不平。
该定义隐含了一个需要在业务上被接受,在技术上需要得到解决的问题,即分户账和总账需要在同一个时间点上进行余额核对。这个同一的时间切片时点–就是日终切日时点(营业日由某一日换到下一日),在总账系统与分户账系统都从属于核心的时代,因为共用营业日,这个问题很好解决,但随着SOA架构和分布式架构的发展,越来越多的专业系统从核心剥离,不同的系统在营业日上保持同步就非常重要(不然就会出现所谓的跨日账问题,A的账记在T日,B的账记在T+1日,造成不平账的幻觉)。为进行这一标准定义,会计日的概念被引入系统设计,系统用会计日来表示一笔账的记账日期,会计日与自然日多数情况下会保持一致,但在从系统切日到跨过24:00的这个时间段中,会有所差异。举个简单的例子:
某银行系统日切设定为23:00,假设当日为T日,则在当晚23:00日切后,以这个时间点为基线,发生在23:00前的所有交易,其账务日期均为T日,而发生在此之后的,即便真实交易时间没过24:00的,其账务日期也在系统中被登记为T+1日。对总分对账而言,系统对分户账的汇总,以23:00这个时刻为snapshot,总账(科目账)的余额,也使用23:00这个时刻。(举例:客户A账户2月19日23:00时有余额10000元,23:40,手机银行转出1000。23:40转出的这一笔1000元,在会计上将反映为2月20日的账,其在银行内部对应的1000元活期储蓄科目账,同样也是在2月20日进行更新–即账务日期为2月20日)。
不同系统间的账务日期同步需要被关注,这一问题可以通过切日时序(作业依赖),也可以通过由核心总控的切日信号通知机制来进行保障,办法很多,关键是系统实现的时候,要时刻绷着这根弦。
广义上的总分核对:狭义的总分核对,即是分户账与总账(客户账)的核对,而广义上的总分核对,则在总分核对之外,还会加入一些其他内容,常见的有:
跨系统往来科目的核对。跨系统往来是银行系统分离后,为了满足“有借必有贷”会计记账原则而引入的解决方案,其本质是一类过渡性质的科目,从业务原理上讲,这一类在日终的时候进行事后检查,是为了保证跨系统之间的事务一致性。举个简单的例子:假设某银行,存款系统和贷款系统是两个独立的系统,这时,如果为客户放一笔50000元的款,其处理为,先在贷款系统放款,贷款系统会记录贷款账:DR XXX贷款 50000。然后调用存款接口,将放出来的钱,记入客户的存款账户,存款系统记存款账。CR XXX活期存款 50000。两个系统都出现了单边账,为了满足“有借必有贷”的记账规则,实际记账中,一般会这样:
这个系统间往来,以“借-贷”方式捉对出现,显然地,如果两个交互的系统事务一直同时成功或者同时失败的话,那么“系统间往来”这个科目,晚间科目余额必然为0。如果不为0,则意味着出现了单边账–不时会伴生重复付款等严重事故。
总总核对。更准确的描述是小总账与大总账的核对。在银行系统设计中,一般会有一个全行性的科目账系统-称为大总账,另很多分户账系统,比如票据系统、资金系统、从核心剥离出来的贷款系统等等,单一系统为了账务管理便利,也会在分户账之外,设置自己内部的科目账–是为小总账。这些系统在进行账务处理时,会既更新自己的科目账,又请求更新大总账。此时,为了保证系统账务核对的准确,就会出现“总-总核对”的操作。示意如下:
明细核对。在部分商业银行的实践中,相关核对要求会更加严谨,在总分、总总核对之外,还会将更新分户的明细流水与更新科目账的流水明细进行勾稽,即为明细核对。其示意如下:
除此之外,在早期的银行系统设计中,还会有日终对跨柜组科目的核对,有些银行会将管理外币敞口系统中的余额与总账的科目账余额单列一类进行核对等等。但这些,其实本质上还是可以归类到“往来类核对”或“总分类核对”的范畴,不作赘述。
解开总分核对的迷思
在做银行系统开发的小伙伴的脑海中,不知道是否曾有过这样的迷惑:1)、总分核对为什么需要这么大费周章,直接将分户加总一下,用这个数更新对应的总账,不是可以永远保持一致吗?2)、账户里面的钱就是个数字,拥有数据库权限的话,给自己的账户记录Update一下账户余额会如何?当然,→
了解过账务处理原理和总分核对的核对内容后,可以稍微回答一下这两个问题了:对于第一个问题,总分核对的实质可以表述为:银行系统在进行余额更新操作时,需要由交易驱动,记录交易流水,这一驱动同时作用于分户和总账,前者用于反应客户账户(分户)的变化,后者用于反应银行自己的账本的变化,总分核对的目的,就是保证银行记录的客户账(用分户账表述可能更准确,因为内部户也需要总分核对,但最早的起源确实是对客)与银行自己的总账的一致性。从实现原理角度看,基于交易请求,实时更新分户账,与基于交易流水,日终汇总后,更新科目账,是分账户与总账更新的基本机制。如下示意图:
但在系统实践中,因为总账需要分录什么科目账,通常需要根据分户系统(比如存贷款、票据、资金、国际结算、理财)的业务场景决定,实际上的科目账更新流水,由分户系统进行组织,再加上很多商业银行在总账前,引入会计引擎支持异步记账模式,面向实操的系统实现方案多数按如下方式构建:
总而言之,总账是基于交易流水(日志),汇总后进行更新的,绝不是将分户汇总后,再更新科目账。至于第二个问题,则可以回到一致性保持机制来做些审视…
从技术角度的解析
由于行业的特殊性,商业银行对事务强一致性有着近乎苛刻的痴迷(事实上,不分银行在执行广义的总分核对时,其业务名词已经从“总分核对”,变为了“业务一致性核对”),事务满足ACID原则在很长一段时间内是需要无条件遵守的准则。在大集中时代,核心系统几乎代表了一切,所有功能都在一个系统中,事务一致性通过数据库的MVCC机制(通常使用DB2或Orcale,或IBM的VSAM文件系统)即可得到保证。随着行业的高速发展,商业银行系统一方面需要满足越来越专业化的业务要求,对应的越来越多的业务系统从核心剥离,单独建设,SOA架构应运而生;另一方面,随着服务的客户越来越多,对海量高并发的支持,也成为商业银行系统建设必须面对的问题,为解决这一问题,分布式架构中的BASE原则被原来越多的引入商业银行系统架构实践中–即牺牲交易过程中的强一致性,在优先保证服务的可用性(Basically Available)的情况下,保证数据的最终一致性。
SOA架构与分布式架构模达成BASE的技术手段不一样(分布式架构下事务一致性通过分布式事务管理器,常见的如Seata来实现,SOA架构中,则需要应用系统开发人员手撸“冲正管理器”),但保证事务一致性的原理并无二致。保证最终一致性的模式(在不引入缓存和异步消息的情况下),由三板斧组成,即“查询”、“定期校对”以及“补偿处理”。其中,补偿处理分为系统开发的补偿机制,以及依靠业务人员手工进行的补偿处理(一般是营运岗或集中作业岗)。自动补偿机制,一般是系统的冲正管理器基于核对结果自动发起的交易冲正(主调系统事务回滚后,根据核对结果通知被调系统同样进行交易回滚)或补偿执行(常见于设置了中间状态或持久化了消息的情况,确保事务执行达到最终状态)。手工补偿机制,则是根据产生的核对报表,比如总分不平报表,跨系统往来不平报表,支付业务中的对账不一致报表等,在查明原因后,依靠业务人员手工处理达到事务最终一致的处理。
以一笔贷款放款为例:贷款系统在完成借据建立、还款计划生成、交易记录登记及贷款账分录后,发送交易请求至存款系统(将贷款资金入存款户),若超时未获得存款系统的返回,则应用3板斧,先查询交易请求在存款系统是否得到处理,若存款系统正常处理了,则根据处理成功与否进行补偿处理–选择提交或回滚贷款系统自身的事务(保证了一致性);如果查询发现交易请求未送达,同样需要进行补偿操作–贷款系统需要回滚自身的放款处理,即整笔交易回滚。除此之外,用于连接存贷款的跨系统往来科目,则成为日终核对贷、存处理是否一致的判断抓手,用于定期核对,发现相关的问题。
需要说明的是,“定期核对”在不同的机构有不同的定义,技术能力强,工具和运维平台完善的机构,可以实现流水的T+M核对(即分钟级的核对,并由系统抛出告警),而绝大多数的机构,一般就只能依靠日终的核对。
谈到这里可以发现,总分核对,从技术角度看,不过也只是定期核对以保证一致性的保障机制的一类,其与支付业务中的跨机构对账,以及分布式事务管理器要保证的事务一致性,应用系统中的冲正管理器要实现的目标,本质上是一致的。只是,随着经营理念的不断进化,为强一致性牺牲可用性的模式正逐渐让位于尽量保证服务可用,在软状态下,保证最终的一致性即可。从这个意义上说,总分不平本身并不是什么大不了的事(特别是一些零散的陈年旧账,或者散碎的乱账,那种重复付款或重复扣款导致的重大长短款事故不在此列,如果只是几分钱或者金额不大的错账,又实在查不清楚的,挂账就好)。
作为一位有追求的码农,在进行银行系统设计和开发时,充分理解业务本质,将有助于我们在面临可用性和一致性的权衡时,既不墨守成规,也不盲动冒险,而是基于理性,作出自己的判断,设计出好用且严谨的系统。