账务交易一致性设计概述

对于账务交易最重要的就是交易一致性,即给客户反馈正确的一致的结果。交易一致性并不是一个简单的话题,说来话长了。下面我结合项目的一些经验,谈一下我认为重要的地方。

交易本身大体分为三类,联机交易、批量交易、批量联机交易(即联机实时返回多笔交易的结果)。下面分别对于不同的场景进行说明:

1 联机交易

1.1 接口设计

从接口设计角度,对于联机交易一般包括两个接口,账务发起接口、交易结果查询接口。其中联机交易接口用于发起实时交易,并实时返回结果。交易查询交易则用于对账使用,用于确认账务成功与否。

账务发起接口:

此接口输入至少应包括如下字段:客户标识、客户交易流水号(用于客户对账使用)、其他账务相关的要素包括付方账号、收方账号、金额等(具体根据业务需要来定)。

输出至少应包括如下字段:交易结果代码、错误码、错误信息、系统交易流水号(可选)、交易日期(可选)。交易结果代码包括成功、失败、不确定三种状态,其中当交易超时等异常时反馈不确定状态,由客户调用“交易结果查询”接口进行对账。另外两个可选字段系统交易流水号用于表示本系统内部的交易流水号,方便排查问题;交易日期表示交易发生的记账日期,以便客户知道这笔账属于哪日的交易,如失败“交易日期”可以为空。接口务必保证交易结果代码的正确性。

交易结果查询接口:

此接口仅用于账务交易反馈不确定或超时时对账使用,对于需要列表查询的需求建议另外使用单独接口来做(例如支持分页,支持模糊查询等),这主要是出于性能、可维护性如流控等方便的考虑。对于交易结果查询接口输入字段应包括:客户交易流水号、系统交易流水号(两者二选一输入)、客户标识,输出字段除了包括账务发起接口的交易结果输出字段外,还应该包括查询结果代码、查询错误码、查询错误信息,用于反馈这笔查询交易是否查询成功,是否应该后续继续查询。对于同时包括报文头、报文体的交易,查询结果代码等可以放在报文头中,而交易本身结果可以放在报文体中。

1.2 其他说明

上面提到的客户交易流水号由客户生成并上传,生成规则应保证同一个客户内部全局唯一,以便用于对账。注意不要采用一天内唯一的概念,由于时间并不是一个双方都认可的值,特别是涉及到日切时。可以采用一周内、一个月内唯一的概念,这需要在接口中提前约定。此客户交易流水号涉及到判重的问题,系统应保证交易唯一性,建议通过数据库唯一索引来做(具体实施方式将在后续文章介绍)。

系统交易流水号由我方系统生成,应保持全局唯一性,此流水号建议包含日期、时间信息,以便排查问题。

交易结果代码:由于此代码十分重要,程序务必保证其正确性。应用应将此字段放在应用能够完全控制的地方,例如对于报文包括报文头、报文体两部分,而报文头由框架负责填充,此时建议将此字段连同错误码、错误信息一起放在报文体中,对于报文头中的错误和客户约定为”处理中”状态,这是为了避免由于框架原因而导致原本正确的交易返回失败。此规则适用于账务发起接口及交易结果查询接口。

如需提供交易结果列表查询功能,应发布单独接口。此接口应支持分页查询、或是查询下一页功能(可通过在输入中增加上次查询最大系统流水号字段实现),支持按账号、按金额、按日期等进行筛选。注意此处日期包括:客户提交日期、系统营业日期、记账日期,这些日期概念是不同的,由于此接口仅用于查询不用于对账,如果业务允许可以仅支持一种,建议使用客户提交日期。

1.3 交易超时设置

交易在每个外呼中均应该设置超时时间,超时时间应该满足“漏斗原则”,防止在后端未处理完成时前端已经失败返回。漏斗原则是指从客户前端->中间转发服务器->应用服务器->账务核心服务器,各个节点的超时时间应该以此减少。对于特殊情况不能满足漏斗原则的情况,应该由应用服务器在程序逻辑上保证交易一致性,例如返回处理中并提供异步对账功能,或是提供冲正功能。若采用冲正方式,违反漏斗原则会造成很多交易结果不确定,交易应该在设计阶段考虑各种情况下超时如何保证交易一致性(冲正比较复杂,在此不做详细介绍)。

交易超时还包括一点:避免异常情况下查询交易早于账务发起交易到达。这一方面可以通过控制查询交易和账务发起交易的间隔来保证,例如约定超时时的查询间隔30s,但即使这样在特殊场景也会有问题。为了防止此问题可以在交易报文中设置交易发起时间、交易剩余处理时间,这两个字段在进入我系统后由前端系统生成并赋值(不能由客户填充),如客户通过外围系统接入此字段由外围系统填充。交易剩余时间一般设置为30s,在消息传递的各个环节应该对剩余时间进行重写(包括中间系统、应用系统等),如剩余时间为0,则不应该进一步传递消息,应直接返回失败。对于应用系统(即需要保证交易正确性的系统)在记录流水前也应该判断此剩余时间,如为0则应直接返回失败而不记录流水。

应用设计者应了解每只账务交易的一致性保证机制,从设计上保证一致性。对于账务交易尽量不要支持重发,重发很容易导致交易重复提交,且不容易识别查询返回结果,除非服务方和调用方系统进行周密的设计不建议采用。

2 批量交易

2.1 接口设计

批量交易是指客户通过上传批量文件的方式发起的账务交易,这种交易一般为异步处理。一般包括批量文件上传交易、批量结果查询交易。

批量文件上传交易

批量文件上传交易主要完成客户文件上传功能,系统如接收文件成功应返回客户文件接收成功。接口输入报文应包括客户标识、客户批次流水号(用于查询批量整批结果)、批量文件路径及名称、批量总笔数、批量总金额。输出字段和联机单笔交易类似,至少应包括如下字段:批量交易结果代码、错误码、错误信息、系统批次号(可选)、交易日期(可选)。

接口的其他注意事项包括交易结果代码、唯一性约束和联机接口一致。除此之外还有以下几点需要注意:

  1. 客户应保证批量文件早于联机报文到达,以便根据报文解析文件时文件已经发送完毕;
  2. 对于批量文件名称应保证唯一性,可以对于每个客户使用单独的目录。这一点需要和客户提前约定;
  3. 文件应使用特定分隔符分隔,需要保证分隔符和正常业务字段不重复,例如 @ # 等;
  4. 文件内每笔交易应包含客户交易流水号或批内子序号,用来查询结果时标识每笔明细;
  5. 系统对于批量的联机处理,至少应包括记录批量流水记录;对于后续处理如文件解析、校验,记录批量明细信息、业务逻辑校验,业务处理可以根据业务、性能需要考虑是否包括在联机处理中。
  6. 系统联机处理时应对每批文件的笔数进行控制,具体可以根据业务需要来,可以为200笔或2000笔。

批量结果查询交易

客户通过此交易可以查询批量处理的结果,包括两部分:一是批量整批的结果,一是每笔批量明细的结果。为了处理简单,可以当批量整批处理完成后再返回批量明细的结果,如果确实需要实时返回批量明细的结果,需要在设计时保证返回结果的正确性,包括明细的完整性、正确性(如批量太大不建议采用这种方式)。

输入接口应包括: 客户标识、客户批次流水号、系统批次号(可选);

输出接口应包括:1.整批信息:批量交易结果代码、错误码、错误信息、系统批量流水号(可选)、交易日期(可选);2.明细信息:客户交易流水号/批内子序号、明细交易结果代码、错误码、错误信息、系统批量子序号(可选)、交易日期(可选)。明细信息可以根据接口定义是否返回,如只有整批处理完再返回结果,可以定义为:当整批信息不为整批失败、处理中时会返回交易明细结果,当整批结果为交易成功时应返回明细结果。

这里需注意以下几点:

  1. 上述输出接口字段建议放在报文体中,通过报文头的系统交易结果、错误码、错误信息来表示查询交易本身的结果,如交易超时等;
  2. 如系统支持的批量文件较大时,需要通过文件来返回交易结果,返回报文中没有明细信息,但应该有明细结果文件路径及名称。文件名可以和客户输入文件名加后缀方式来对应。结果文件建议作为批处理的最后一步给客户提前生成好(建议在修改整批状态之前,以免客户查不到文件),并和客户约定保存多长时间。
  3. 为防止批量状态卡死,系统应该有专门的检测自动任务来检查异常的批量状态,并针对错误进行相应的处理(包括转人工处理)。
  4. 批量结果查询交易应和批量历史流水列表查询分开,以保证系统性能和可维护性。

2.2 其他说明

批量交易的其他注意事项,如判重、交易结果、超时,可参考联机单笔交易中的说明。在设计批量交易时应将整批作为一个整体考虑,结合系统非功能要求确定应支持的功能点,切记为了所谓业务需求,盲目实现不必要的功能。

3 批量联机交易

这类交易相当于系统提供的单笔交易的批量接口,但整批的结果要求同步返回(如不同步返回可以参考上面的批量交易)。这类交易比较特殊,为了保证交易一致性,需要将这多笔交易当做一笔来看待,作为整体记录流水,而不是简单的循环调多笔。批量联机交易一般不要直接发布给直连客户,可以作为界面或是内部调用的性能优化手段,如果没有性能问题应尽量采用循环单笔的方式。

输入接口应包含:客户标识、客户交易流水号[支持列表]、其他单笔交易的业务字段[支持列表]。输出接口应包含每笔交易的结果信息列表。对账接口应支持按照客户交易流水号列表来查询结果。

在交易设计时需要考虑如下几点:

  1. 对交易支持的最大笔数进行限制,这个限制的建议值为超时时间内能处理的交易笔数(包括启动多个并发、不启动并发两种情况),最大值为系统可以保证交易一致性的最大笔数。
  2. 交易处理方式可以考虑以下几种:a.将多笔交易作为一个整体提前记录流水信息,然后逐笔处理[建议];b.直接调用逐笔交易当做单笔处理,如已超时未处理记录直接返回失败,不做处理[可以满足一致性要求,但不建议];c.直接当做单笔处理,超时仅返回处理中,由判重功能来保证不会有账务问题。[不建议,客户无法知道应该等多久查结果、再次发送]
  3. 查询结果交易需要保证在交易处理的任何时点的结果都是正确的,不能仅查到部分交易的结果,故应该将多笔当做一个整体来预计流水。
  4. 多笔交易一般是有关联的,建议对中间数据进行交易级别缓存,以提高性能。
  5. 是否要采用并发处理建议能支持客户选择,由于并行处理对于某些场景是会影响交易正确性的。(PS.有些客户是在乎顺序的)
  6. 此交易会长时间占据联机服务器的线程,会大大降低系统的吞吐量,采用并发并不会使情况缓解。针对此交易设置单独限流策略。

上面对于三类交易的接口设计以及一些注意事项进行了介绍,后面文章再对账务交易的一些设计细节进行详细描述。

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《ITechLib》

留言:

(lesstile enabled - surround code blocks with ---)