背景:
小陈在老王和龙哥的要求下,要重构一个旧的财务库存系统。那么第一件事就是了解财务库存系统干啥的。
财务库存系统,系统主要职能在于处理上游wms(仓储系统-物理仓储)推送的库存指令,对应处理,生成财务库存数据,作为结算依据。(简单理解,对比物理仓储,增加了财务信息,如公司,税,供应商,po-采购批次,成本计算等)
上下游:
wms(物理仓储) -> inv(财务库存) -> ap(财务应付)
小陈继续研究,先看看旧系统怎么玩的,能不能复制粘贴。
旧系统方案:
采用批处理,单线程操作,一批加载一定量数据,因不存在并发,不涉及竞争问题,纯逻辑。
定方案前,小陈想起老王/龙哥的指导性要求:性能必须超过旧系统10倍,mysql分库分表,支持10倍业务数据量。
小陈先理解一下业务:
纯业务角度思考,现有量实质上是一张表,维护每个商品当前剩余数量信息。
库存指令下达时,根据指令更新现有量。
比较难搞的几个点:
几乎全部库存指令,都涉及现有量(商品剩余库存)的操作,如何兼顾性能和准确性,并符合财务业务逻辑。
对现有量的操作,实质上是一个竞争,并发安全的问题,如:
指令1扣减商品1库存,指令2扣减相同商品库存,当前符合条件的现有量只有1条,两条指令只能成功一条,失败一条。
分库分表:
新系统必然要分库分表,那第一个事就是定分库字段,库存业务以po驱动,基本关键业务表都有po字段,所以定的是po分库。(事实上这里错失了一个重要的机会,不采用sku-商品分库)。那么,db架构可能是这样:
一个基础库,存储不需要分库的基础数据
sharding库N个,存储数据量比较大的,需要分库分表的数据。
问题来了,现有量表放哪合适?
小陈继续细思,如果放base库,业务表都是用po分库的,如库存调整表(保存上游下发的库存指令),那么这些指令处理完成以后,对现有量的操作,最好也是在相同的db里面完成,这样才能简单的由db层面完成事务而不是踩进分布式事务的大坑。
如果放sharding库,似乎可行,正常现有量都附带有po,但有些业务场景,现有量的po会发生变化(月结时清空现有量上的po,让数据过校验),甚至为空(历史数据),发生变化时就是一个多库事务。
经过一番思索,小陈在领导指导下终于有了V1.0:
1 表存储: 现有量拆分成两部分,base库中维护现有量汇总表,存放已汇总的现有量数据。sharding库中维护现有量流水表,也采用po分库。每个指令(如果现有量充足)处理完生成对应的流水记录,这样指令的处理会在一个db中完成。(update指令状态为success,插入流水,插入业务数据)
2 现有量汇总:流水表的记录需定时汇总到汇总表,不然过多的流水记录,会影响查询性能,这里要增加一个游标表,标识当前汇总到哪里(以时间为例子)。
比方说游标表存储的时间是2018-10-01,则创建时间在这个时点之前的流水数据,已经汇总到汇总表,在这个时间之后的数据则未汇总。
现有量汇总 = 查询当前游标时点到目标游标时点的数据,汇总到汇总表并更新游标,汇总表和游标表均在base库,一个事务搞定,并不影响sharding库数据。
3现有量查询:查询base库数据 + 大于游标时点的sharding库数据
4现有量流水表清理:删除掉创建时间早于游标表时间的数据,保持流水表干净,提高查询性能
5增加sku锁,对一个sku,同一时刻只有一个线程可以修改现有量。
6为了性能,小陈决定再加一层缓存。
6.1 现有量查询时,优先查缓存,如果缓存为空,查询后,将结果写入缓存,key是sku,value是现有量+流水
6.2 流水处理后,往缓存追加新的流水
6.3 缓存里面key对应的value过大时,重新从db load数据(db层面一直在汇总,重新拉的数据量会大幅减少,如果不处理,value过大会占用网络io)
7 同db数据组批处理
小陈经过分析,感觉似乎凑合,开工撸代码,上线,结果来事了。。。
上文的3现有量查询,其实并不是描述的那么简单。
伪代码
B1 查询base库现有量
B2 查询base库游标
B3 查询sharding库数据
B1,B2中间,如果发生了现有量汇总,则是标准不一致,出错是正常的。(是否B1,B2一个查询sql查出来就可以避免?待分析)
于是有了一个新的锁。。。
V1.2
8 增加现有量查询锁,现有量汇总时,汇总哪个sku锁哪个,被锁的sku无法查询,自旋等待,超时退出后续重试。
好了,系统上线了,看起来都稳定了。小陈回过头看看自己怼出来的这个方案,有啥好跟不好呢?
优点:规避了多库事务;业务处理纯单库事务,组批处理,性能比旧系统提高10倍。
缺点:引入了两层锁,业务量到一定程度,是明显的瓶颈。
YY:如果采用sku分库,可能一切都不是问题。
反正上线了,小陈怼新的系统去了,那么大神们,我们应该如何优化呢?

小陈在老王和龙哥的指导下,对旧财务库存系统进行重构,以提升性能和处理能力。新系统采用分库分表策略,通过流水表和汇总表分离现有量数据,引入缓存和锁机制优化并发和查询效率。
1753

被折叠的 条评论
为什么被折叠?



