概述
那么不使用缓存(redis、memcache),如何设计高效抢购业务呢?
常见的抢购业务主要有:
商品抢购
券抢购
红包抢购
今天咱们就谈谈如何对这些抢购业务做统一设计,只使用Mysql做高并发活动。
我们先看下面一张表,分别标出了这三类业务涉及到的核心数据量:
核心数据量
数据量商品库存券库存红包库存数据金额
1.总量
totalNum
totalNum
totalMoney
总金额
2.销售量
sellNum
sellNum
sellMoney
领取金额
3.锁定量
lockNum
lockNum
0
锁定金额
4.库存量
stockNum
stockNum
stockMoney
库存金额
5.退货量
refundNum
refundNum
0
0
6,库存池
inventory
inventory
-
-
我们再看下这些业务涉及到的核心节点的数据量变化
核心数据量变化(变化量为n)
节点名称总量销售量锁定量库存量退货量
下单
totalNum不变
sellNum不变
lockNum+n
stockNum不变
refundNum不变
取消订单
totalNum不变
sellNum不变
lockNum-n
stockNum不变
refundNum不变
支付
totalNum不变
sellNum+n
lockNum-n
stockNum-n
refundNum不变
核销
totalNum不变
sellNum不变
lockNum不变
stockNum不变
refundNum不变
退款
totalNum不变
sellNum-n(或不变)
lockNum不变
stockNum+n(或不变)
refundNum+n
节点设计
我们知道,每个操作节点最少可对应一个操作。而我们为了保证接口效率最高,我们需要尽量少的使用sql操作,如果每个接口只有一次数据操作那是最好的。
但是,每个接口的逻辑可能都会涉及到若干数据业务操作,而我们为了能让这些抢购业务性能尽量好,那我们就要尽量把接口原子化设计。而在这些接口中,下单操作时重中之重,只要把这个下单接口设计好了,后续流程基本都没啥大问题。
下单接口设计
那我们来分析一下下单接口的设计业务:
检查库存是否够用
防止并发超卖
锁库存
等等...
那这些要求改如何同时满足呢?那就要我们尽量合理使用核心数据量了!
那我们在设计库存表的时候,尽量把总量、销售量、锁定量、库存量放到一起,可以如下设计:
CREATE TABLE `goods_stock` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`SPU_ID` bigint(20) NOT NULL DEFAULT '0' COMMENT '商品SPU_ID',
`SKU_ID` bigint(20) NOT NULL DEFAULT '0' COMMENT '商品SKU ID',
`STOCK_LEFT_NUM`int(11) NOT NULL DEFAULT '0' COMMENT '剩余库存数量',
`STOCK_SALE_NUM`int(11) NOT NULL DEFAULT '0' COMMENT '售卖库存数量',
`STOCK_LOCK_NUM`int(11) NOT NULL DEFAULT '0' COMMENT '被锁定的库存数量',
`STOCK_TOTAL_NUM`int(11) NOT NULL DEFAULT '0' COMMENT 'SKU总库存量,0表示不限制库存',
`STATUS` tinyint(4) NOT NULL DEFAULT '0' COMMENT '本条记录状态,0-有效,1-无效',
`CREATE_TIME` datetime NOT NULL COMMENT'创建时间',
`UPDATE_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT'更新时间',
`VERSION`int(11) NOT NULL DEFAULT '0' COMMENT '乐观锁版本号',
PRIMARY KEY (`ID`),
KEY `IDX_SPU_ID` (`SPU_ID`),
KEY `IDX_SKU_ID` (`SKU_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品SKU库存表';
其他字段在实例中省略了。
我们看看如何使用这一张表满足上述要求:
1,检查库存是否够用:
STOCK_LEFT_NUM >= n
2,防止并发超卖:
利用数据库行级锁防并发
WHERE SKU_ID = ${sku_id}
3,锁库存:
STOCK_LOCK_NUM = STOCK_LOCK_NUM + n
那么,具体的下单、取消订单、支付等业务节点就可以如下实现:
1,下单
UPDATE `goods_stock`
SET `STOCK_LOCK_NUM`= `STOCK_LOCK_NUM` +${lockNum}
WHERE `STOCK_LEFT_NUM`= ]]>${lockNum}
AND `SKU_ID`=${skuId}
AND ${lockNum} ]]> 0
当该操作执行成功,再处理其他逻辑;如果失败,就直接返回下单失败。
2,取消订单
UPDATE `goods_stock`
SET `STOCK_LOCK_NUM`= `STOCK_LOCK_NUM` -${lockNum}
WHERE `SKU_ID`=${skuId}
AND ${lockNum} ]]> 0
3,支付订单
UPDATE `goods_stock`
SET `STOCK_LOCK_NUM`= `STOCK_LOCK_NUM` -${lockNum},
`STOCK_SALE_NUM`= `STOCK_SALE_NUM` +${lockNum},
`STOCK_LEFT_NUM`= `STOCK_LEFT_NUM` -${lockNum}
WHERE `STOCK_LOCK_NUM`= ]]>${lockNum}
AND `SKU_ID`=${skuId}
AND ${lockNum} ]]> 0
目前MySql+SD硬盘的话,MySql事务并发量达到2000是没啥压力的,所以一般并发2000左右的都可以直接使用MySql数据库设计业务逻辑,无需使用Redis缓存。
这里只是给出了商品库存核心逻辑,券和其类似,不过还多一点库存池(存放券码),其实这个可以放到后台去处理了;红包比这个更简单,只有下单(领红包)操作。
共同学习QQ群:793305035
最后
以上就是大气小猫咪为你收集整理的java限时抢购_Java生鲜电商平台-生鲜电商限时抢购功能设计与代码实战(小程序/APP)...的全部内容,希望文章能够帮你解决java限时抢购_Java生鲜电商平台-生鲜电商限时抢购功能设计与代码实战(小程序/APP)...所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复