thinkphp6电商项目中sku库存管理采用“redis前置校验+数据库行锁落库+定时补偿+事件解耦”四层机制:先用lua脚本原子校验redis库存,再以select for update锁定并扣减db库存,未支付订单由定时任务回滚,最后通过inventorychanged事件通知下游。

在ThinkPHP6.x电商项目中,商品SKU规格生成与库存扣减是核心业务环节。当用户提交订单时,系统需依据所选规格组合精准定位SKU,并原子化完成库存校验与扣减。以下是实现该逻辑的具体方法:
一、基于规格值组合生成SKU编码与库存初始化
SKU的唯一性依赖于规格值的有序组合,需将用户可选的规格(如颜色、尺寸)及其值进行笛卡尔积运算,生成所有合法组合,并为每个组合分配独立库存字段。数据库中SKU表需包含规格标识字段(如spec_values)及库存字段(stock),便于后续匹配与更新。
1、定义商品规格模板,在后台录入“颜色:红色、蓝色”“尺寸:S、M、L”,并保存至spec_template表。
2、在商品编辑页选择启用的规格项,通过JavaScript前端生成实时组合预览,后端接收组合数组并序列化为JSON字符串存入sku表的spec_values字段。
3、为每个组合插入一条SKU记录,stock字段初始设为管理员填写的数值,spec_values字段值形如{"color":"红色","size":"M"}。
二、下单前基于Redis原子校验SKU库存
为避免超卖,需在创建订单前对所选SKU执行高并发安全的库存校验。采用Redis的DECRBY指令配合WATCH机制或直接使用Lua脚本,确保“读取-判断-预留”三步不可分割。
1、将各SKU的库存映射为Redis哈希结构,键名为sku:stock:{id},字段为available,值为当前可用库存数。
2、用户提交订单时,后端解析所选规格组合,查询对应SKU主键ID,并拼接Redis键名。
3、执行Lua脚本:先获取available值,若大于等于订单数量则执行DECRBY并返回1,否则返回0;脚本执行结果为0时立即中止下单流程并提示库存不足,请刷新页面重试。
三、使用数据库行级锁同步更新库存与订单绑定
Redis仅作前置校验,最终库存变更必须落库以保证事务一致性。通过SELECT ... FOR UPDATE锁定SKU记录,防止并发修改导致数据错乱,再更新库存并写入订单SKU关联表。
1、开启数据库事务,执行SELECT * FROM sku WHERE id = ? AND stock >= ? FOR UPDATE。
2、若查询无结果,抛出异常并回滚,前端显示该规格库存已被抢购完毕。
3、执行UPDATE sku SET stock = stock - ? WHERE id = ?,同时插入订单明细表order_item,字段包含sku_id、order_id、quantity、price等。
四、定时任务补偿未支付订单释放库存
用户下单成功但未在规定时间内支付,已扣减的Redis库存和数据库库存需恢复。借助ThinkPHP6的命令行调度功能,配置每5分钟扫描一次待释放订单,触发库存回滚逻辑。
1、查询order表中status = 0且create_time早于当前时间30分钟的记录。
2、遍历其关联的order_item,获取对应sku_id与quantity,执行UPDATE sku SET stock = stock + ? WHERE id = ?。
3、将对应订单status更新为-1,并向Redis中对应sku:stock:{id}的available字段执行INCRBY操作,数值为原扣减量。
五、通过事件监听解耦库存变更通知
库存变动可能触发价格策略调整、预警推送、销量统计等下游行为。利用ThinkPHP6的事件系统,将库存更新动作发布为InventoryChanged事件,由独立监听器响应,避免核心流程侵入无关逻辑。
1、在SKU库存更新成功后调用event('InventoryChanged', [$skuId, $changeAmount, $afterStock])。
2、编写InventoryAlertListener监听器,判断$afterStock SKU {id} 库存低于预警阈值。
3、编写SalesStatListener监听器,将销量增量写入聚合统计表sales_daily,字段包括date、sku_id、quantity_sum。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











