1. 技术背景
库存模块是一个更新数据库密集型的模块,无时无刻不在有库存更新操作。数据库性能瓶颈不容忽视,其中数据库对同一行记录的热点更新更是迫在眉睫。
2. 热点商品定义与发现
-
普通商品:下单扣库存并发不高的商品; -
秒杀商品:库存比较少,下单扣库存并发高的商品; -
热点商品:库存比较多,下单扣库存并发高的商品。
特别注意:热点商品 ≠ 秒杀商品
区分秒杀商品与热点商品的意义在于,秒杀商品很快就会将库存扣减为0,且之后就不会再有扣库存请求了,没有必要进行热点分片,因此下文讨论的热点商品分片不包括秒杀商品。
怎么发现热点商品呢,可以通过下面四种方式来确定:
-
运营提供,大促前找运营过促销方案时,发现热点商品,提前配置热点商品白名单; -
统计下单流水,统计最近一段时间下单流水,找出其中频繁扣减库存的热点商品记录; -
统计最近一段时间购物车 TOP 商品,交易链路提供; -
统计最近一段时间商品详情页访问 TOP 商品。
3. 热点商品分片技术方案
3.1. 库存分片记录表,同时开启热点会在库存表有个是否热点字段来标识
// 库存分片表
CREATE TABLE `inventory_piece` (
`SKU_ID` varchar(60) NOT NULL COMMENT '商品SKU',
`WAREHOUSE_ID` varchar(60) NOT NULL COMMENT '仓库ID',
`STORE` int(10) NOT NULL COMMENT '分片库存',
`PIECE_ID` int(10) NOT NULL COMMENT '分片编号',
`CREATE_TIME` datetime(0) NULL COMMENT '创建时间',
`UPDATE_TIME` datetime(0) NULL COMMENT '更新时间',
UNIQUE INDEX `idx_unique`(`SKU_ID`, `WAREHOUSE_ID`, `PIECE_ID`) USING BTREE
);
3.2. 分片库存与分片数量调整流程
热点分片的原理是将原来的一条记录拆分成多条记录,下单扣库存随机扣减不同的记录,以提升单商品扣库存性能上限。那么存放在原有库存表中的记录称之为主分片记录,在分片表生成多条记录称之为次分片记录,也叫分片记录;将主分片的可售库存分配到分片表,这时会扣减掉主分片的前台库存字段,以防止产生超卖。
目前系统配置分片数量至少为2个,因为如果只有1个分片的话对性能提升无帮助,最大分片数量为10个,每个分片库存(包括主分片)至少为100个库存,如果不能达到这些要求,则不会进行库存分片。
分片库存与分片数量如图所示:
3.3. 数据一致性保证
-
从主分片分配库存到分片表以及从分片表回收库存到主分片都会通过数据库事务保证数据一致性; -
Service 层以及外部通过接口查询库存时,会在 Dao 层直接将分片库存加到前台库存上,这样上层代码感知不到分片库存的存在; -
进销存增加库存或者取消订单加库存,直接将库存加到主分片记录上,也不感知分片; -
盘亏库存或者虚拟组合库存拆组,如果检测到热点分片库存,则会从 Dao 层向上抛出异常降级本次操作。
4. 热点商品开启与关闭
-
开启热点定时任务通过执行【热点商品发现】确定热点商品范围,并排除热点黑名单记录,对于未开启热点且可售库存满足分片数量要求的进行库存分片的初始化与分配。 -
关闭热点定时任务检查热点黑名单配置,然后回收分片库存,并关闭库存表热点记录标。 -
调整分片库存定时任务遍历所有热点商品,检查分片库存与主库存,如果分片库存已经减少到了30% 则会自动触发库存分配,同时会考虑分片数量,如果分片数量过多则会回收库存比较少的分片库存。
5. 下单扣分片库存与分片库存准实时调整
5.1. 下单扣库存流程
-
下单前查库存,因前台库存字段是主分片和此分片的库存之和,因此原有逻辑不需要改变,库存不足时直接提示库存不足; -
扣库存时检查主分片热点标有没有开启,如果没有开启,则走原扣减逻辑,直接扣减主分片库存; -
对于开启热点标的记录,会同时将分片库存明细查询出来,随机挑选一个库存足够的此分片进行库存扣减; -
如果没有没有次分片库存足够,则检查主分片是否足够,如果主分片库存足够则扣减主分片库存; -
如果所有分片均不够,则同时扣减多个分片库存; -
扣减分片库存按分片ID固定顺序扣减,保证不发生死锁问题,如果扣减某一个分片库存时数据库返回不足时,会将该次扣减放在主分片上尝试扣减一次,减少因分片库存并发不足但是主分片库存足够的情况下的下单失败。
5.2. 下单扣库存后准实时调整分片库存
-
热点分片扣库存后异步启动线程触发一次分片库存调整; -
如果分片有库存,且至少一个分片库存大于30个库存,则不进行分片库存调整; -
如果所有的分片库存均小于30个库存,则尝试触发一次分片调整,不过这时候会使用分布式锁保证一个商品只有一台机器进行调整,且3秒内一个商品只会触发1次分片库存调整,防止雪崩; -
如果库存还有,则尝试进行分片库存分配,如果库存不多,则此时会尝试关热点。
6. 思考回顾
任何方案都有取舍,此方案牺牲了业务的复杂度,目的是为了减少锁竞争,一定程度上提高了系统的TPS。
原文始发于微信公众号(白菜说技术):性能优化:热点商品库存分片方案设计思考
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/172588.html