余额模型:高频问题分析

变更记录
| 产品版本 | 更新内容 | 更新日期 |
| V4.0.020 | 初始版本 | 2022年05月12日 |
1 简介
本文主要列举一些开发人员(包括二开)在日常过程中,可能遇到的一些开发问题。后续根据问题的收录,会不断更新问题列表。
2 常见问题
2.1 单据:XXX还有余额更新业务暂时未处理完毕。。。
1)背景
为提升余额更新的整体性能和吞吐量;
为了提升数据准确性(在事务一致性、服务异常宕机、数据库和中间件异常等情况下);
余额更新实现了异步化处理方式。
2)简单理解
长耗时的情况下:假设一个单据审核需要更新余额,且更新需要10s,发现其中7s就用在了更新数据库的过程。
同步更新情况下:点击审核需要等待10s才能结束。(真结束)
异步化更新:点击审核等待3s即结束了。后面7s会异步处理。用户不用长时间等待,可用继续处理其他单据。
短耗时的场景下:同步和异步化都是瞬间结束。人感觉不到是同步还是异步化。
3)更新约束
为了确保数据在逻辑上决定的更新可靠,要控制一个单据不能在同一时刻发起多次余额更新,则要确保每一次更新必须等待上一次更新业务完全处理完毕,才能继续进行。因此在长耗时情况下,审核成功后,无法马上进行反审核,需要等一等。短耗时场景下,等待极短,反审核好像是马上可以执行。在系统检测到无法执行余额更新的情况下,则会提示信息息。
单据:xxx还有余额更新业务暂未处理完毕,请等几分钟…. 详情可查看【xxxx】列表。

4)分析方法
出现该提示的原因,非常复杂,其依赖组件较多,影响因素也有很多,比如:配置不对,数据本身错误,服务能力不足等都可能出现。下面逐一介绍排查方法。
1、完全正常现象,按系统提示来,等待几分钟后在试,不要急。
可能原因:系统真的还没处理过来,若同步情况下,可能上一个触发余额的操作(如审核)可能都还没结束。
2、若10来分钟后,还是这样,则要考虑是否有异常情况了,下面按场景逐一来看。
场景①:在新增的单据,首次执行更新对应的操作(如:规则配的更新是审核,那就是审核操作)就出现,而且必现,但是检查对应的列表,并没有对应的数据存在。
常见原因:往往是代码调用导致,比如,余额更新操作,业务代码直接调用的,而且内部重复调度了多次,在第二次执行时比然出现。或者业务有自动处理回滚的情况下,比如,审核成功后,后续还有业务,失败了,代码马上调用反审核。这也是必然出现的。
解决方法:余额更新是服务,要如何处理取决于调用方,1)在间隔一定时间后重现发起;2)合理规划好操作的调用;3)能接受阻塞式调用的,也可以选择传入操作参数,调用kd.bos.dataentity.OperateOption. setVariableValue方法设置参数,需要5.0.017以上版本支持,让余额更新服务阻塞,等待可以执行的时候执行,但是这种会导致整体余额更新的吞吐能力下降,参数设置方法如下图:

场景②:自动化测试,或压测中大量出现,且必现。
常见原因:往往是用例设计时,使用了长流程,比如:用一份数据同时测试保存、提交、审核…一大串操作流程,每一步都完全依赖了上一步的执行结果,导致用例失败,这种用例设计本身是不合理的,这种用例只能测同步流程,异步内容就无法控制了。因为:代码模拟操作往往纳秒级就可以发起调用,而实际场景,比如:审核后,在去执行一个反审核,往往有1-3s的时间窗口,足够异步执行完。
解决方法:1)检查测试数据本身是否符合测试条件;2)用例设计时前后服务数据不相互依赖;3)编排服务调用时,考虑加合理的延时;
场景③: 每个单据必现,且在余额模型》余额日志》完全异步更新中的单据、部分异步更新中的事务、部分异步更新中的单据3个列表中数据,只增加不减少。
常见原因:MQ队列没有消费者。
分析方法:进入环境monitor》基础组件》MQ监控,查询bal_queue.bal.tx_notify的队列。分区队列前缀:bal_queue.bal,后缀是应用的APPID,如库存管理应用单据发起的就是.im,核算发起的是.cal,以库存队列来看,就是bal_queue.bal.tx_notify.im,点击查看消费者,若有消费者,且这些节点确实路由消费im应用的则是正常,否则就是异常的。
解决方案:
1)若没有消费节点,则通知运维人员查看,这种往往出现在二开应用,运维人员不知晓有新增二开应用,没有配置二开应用路由,导致MQ无法判断哪些节点可以创建消费者。
2)若有消费节点,则要看节点是否正确,比如:.im的消费节点,应是库存应用,结果发现还有个qing节点。那么也要找运维处理。这个场景,经常发现在5.0.008及之前版本。


场景④:原运行很正常,某个时间开始有些单据更新和回滚都正常,有些单据就是报提示。而且对应的列表数据中确实有对应的单据存在。
常见原因:程序确实执行不下去,比如:数据有异常,后台把数据调乱了;节点部署的代码不对,缺少代码,或者环境更新导致有些元数据不正确了,都是有可能的,这种往往在非生产环境中容易出现。
分析方法:找到余额模型》余额日志》异步处理错误日志:查看当天错误信息。就要具体情况具体分析,这里的错误信息并发全部都系统或人工处理,大部分是可以忽略的,我们需要找到有价值的错误信息,可能还需要结合日志上的traceid,到monitor中拿到全日志,便于进一步分析。下面介绍几种常见需要人工处理的错误信息。
1)数量溢出了

解决方案:测试环境,则要删除对应单据数据,并且找到对应的余额表的临时快照表清理数据,生产环境(实际业务不可能发生)

2)报缺少插件xxx不存在或者该插件没有实现接口xxx
解决方案:1)检查消费节点是否路由正确,比如:库存单据的请求,跑到qing节点消费,qing节点肯定没有库存的代码,比然缺类。那么就要运维把路由调整正确,若路由正确,则检查节点中是否真的如错误提示的问题。找对应的开发人员去处理即可。
其他一些常见,不需要处理的错误有:1)SQL,有死锁;2)分布式锁申请失败,或超额;3)锁等待,超时异常;4)服务不响应的异常;5)单据:xxx还有余额更新业务暂未处理完毕,因为这些错误,都是极端场景下,为了优先保证数据准确性,报错后待系统自动重试处理的。
3)日志显示,SQL报缺失xxx_TP表,如:T_IM_INV_PER_BAL_TP
可能原因及解决方案:
》往往发生在新搭建环境中,头一次发现。因META库和业务库来源不一致,将带已升级标识的META库和未升级的业务库凑为一个新库,导致整个数据库数据和升级状态不一致,打补丁也无效。这问题可以通过下面脚本判断:
在meta库执行: SELECT * FROM t_bas_deployinfodetail WHERE ffilename = 'kd_1.5.158_update_sp_tb.sql'; 可以看升级时间是否和补丁升级时间吻合。下图是一个案例,显示2022-12-12升级的,这个时间点环境都还没有出来或者可以确定不是这个时间升级的。

处理方式:DELETE FROM t_bas_deployinfodetail WHERE FDETAILID = 查询到的ID; 把记录删除掉,然后再次执行补丁,或研发提供的bos-bal的MC更新包。看到下面日志,即代表升级成功。

》其他非主流数据库不适配,PG、ORACLE、MYSQL、DM、SQLSEVER主流数据库是已验证升级无问题的,但是后续增加的其他数据库则不太确定。一般这种问题在UAT环境就可以测出来,不该在生产才发现。
处理方式:联系研发分析,需要一定的时间研究。
场景⑤:xxx_tl表主键冲突。

原因1):因历史版本在xxx_tl表中产生过异常数据,导致异步数据不能正常消费。
临时解决方案:找到对应的xxx_tl表,注意这个表只有ftxid、fbatchid两个字段。执行select count(1) … 查询是否有数据,有则执行delete 全部清除即可,无需备份。
后续方案:在后续版本中个,会有升级程序统一清理。
原因2):在5.0.011之前的版本中,代码本身存在参数有重复的问题,导致insert无法执行。
解决方案:升级到5.0.011及以上版本。
场景⑥:其他异常情况。
解决方案:需找研发支持分析,提前准备下面信息,拉群沟通解决。为了提升效率,提前准备monitor(公有云不用),查询分析器、余额模型应用使用权限,提单或找研发支持。
2.2 库存不足
在余额模型层面是没有任何数量校验相关逻辑的,类似库存不足、余额不足这样的业务是在具体的余额表更新校验中处理的,因此不同的余额表,负数控制的提示信息往往是不一样的。包括界面,提示内容,都是定制的。下面我们以库存管理中的即时库存余额表负库存为例,分析库存不足,是什么原因。其他余额表逻辑雷同。

如上图,库存单据审核,提示库存不足,首先要明确:这是一种正常的业务控制,提示完全没错。若业务人员认为,这个提示和自身预期的结果不一致,才有必要玩下分析。
分析前,往往需要先确定一下内容。
1)库存数量是否充足,查余额表数量,测试环境,可以加库存,生产环境则必须符合实际业务。
2)查清楚是哪个余额表,哪个余额规则提示的余额不足。——可以查余额模型》余额日志》余额更新日志,直接可以确定出来。
3)熟悉负库存控制逻辑:如即时库存余额表的负库存控制逻辑,如下:
目前有3个级别参数设置。
仓库设置:【全部允许负库存】 开启时,代表该组织该仓库下所有物料库存记录允许负库存,关闭时,则需要进一步看【部分允许负库存】设置;
仓库设置:【部分允许负库存】 关闭时,代表该组织该仓库下所有物料库存记录不允许负库存,开启时,则需要进一步看【物料库存策略-是否允许负库存】设置;
物料库存策略:【是否允许负库存】 开启时,则代表该组织下该物料允许负库存,关闭时,则反之。
校验数量的维度:不同组织校验的数量可能是不一样的,在组织系统参数进行配置(基本数量、库存数量、辅助数量)。
4)要了解到余额更新是一对一准确更新,维度字段是必须完全吻合。
即时库存余额表有20多个维度字段,单据更新余额时,找到对应的余额规则,根据字段映射关系,匹配到余额记录进行更新。需清楚余额规则有哪些,维度字段如何映射的,发生数据是怎么映射的。余额更新时是按照余额规则,来源单据数据通过字段映射来匹配到相应的即时库存数据。
按以往问题分析90%以上是维度对不上导致。如:货主类型对不上、货主对不上;出库货主配置的入库货主等;文本字段前后加了空格,看不出来。。。,当人工实在排查不出来,结合环境情况,开启负库存,让单据先审核,在看下余额记录变化,若你认为要出库的记录没变,多了一条负的,则就是维度对不上导致,找到哪个维度对不上,这种情况不能看前端界面显示的编码和名称来比对了,必须是后台数据ID,若是你认为要出库的记录变成了负的,那就是库存不足,不是程序问题。注意:生产环境切记不能随便修改负库存配置,找到问题后,数据要还原。
垃圾数据导致,在非生产环境常出现,发生余额更新后,有对余额表、余额规则做了调整,历史数据没有处理。这是可以选择情况所有即时库存数据或者重算即时库存。
若还无法定位分析,可以联系研发协助分析。
2.3 余额列表界面看着两条余额完全一样,就数量不一样
1)先检查余额物理表索引情况,即时余额表,fkeycol是有唯一索引才对的,期间余额表:fperiod+fkeycol有组合唯一索引才对。无索引,程序是无法保证唯一的。这种往往会在二开独立开发的余额表常见。
2)排查索引因素后,只能在查询分析器,查询这个两条余额的所有字段,维度字段挨个对比。可以发现个别维度前端显示一样,后台确实不一样。这种场景也非常常见,往往是某个基础资料同名(编码OR名称)了。还有就是某个基础资料被删除了,页面显示不了名称,和本身空值的数据看起来一样了。


3)若维度字段也排查了完全一样,但是fkeycol字段不一样。那么铁定无疑,其中有一行数据keycol是错了,Keycol和维度字段一旦生成,余额引擎是不会再做修改了。,对不上,往往是有程序改了余额记录的维度值。这个时候二开就要开始排查代码,找原因了。这种也是有客户出现过的。
2.4 扩展和继承到底怎么用
余额表和余额规则都是元
余额模型:高频问题分析
声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。



