以下是一篇技术实现导向 的文档,具体是《体育直播平台的积分商城》 架构图描述、数据库设计关键点、Redis+消息队列的联动逻辑、接口调用流程示意、核心代码结构设计思路等。
商品兑换、库存扣减与订单处理全流程 + ThinkPHP + Redis + MySQL 实现方案
项目方:东莞梦幻网络科技 体育直播系统源码
一、系统总览与技术选型
1.1 系统目标定位:
在体育直播平台中,积分商城服务承担用户积分消费与激励转化核心角色,需支持:
- 高并发兑换处理(热点商品)
- 强一致性保障(库存扣减、积分扣减、订单创建必须一致)
- 商品/任务/用户等模块联动
- 虚拟与实物商品多种类型支持
1.2 技术架构图(逻辑拓扑)
┌─────────────┐
│ 用户端 │
└────┬────────┘
│ 兑换请求
▼
┌─────────────────────┐
│ 积分商城控制器(ThinkPHP) │
└────┬────┬──────────┘
│ │
商品模块校验 ──┘ └───► 用户积分账户系统(MySQL + Redis缓存)
│
▼
兑换服务调用链:
┌──────────┬──────────────┬─────────────┐
│ 扣减库存 │ 扣减积分(流水) │ 创建订单记录 │(本地事务或补偿机制)
└──────────┴──────────────┴─────────────┘
│
▼
消息推送(RabbitMQ)更新库存状态/订单流转
│
▼
┌──────────────────────┐
│ 订单异步处理(定时任务、状态推进) │
└──────────────────────┘
二、数据库设计核心结构(MySQL)
2.1 积分账户表:user_points
字段名 | 类型 | 说明 |
---|---|---|
id | bigint | 主键 |
user_id | bigint | 用户ID |
point_balance | int | 当前积分余额 |
updated_at | datetime | 最后更新时间 |
2.2 商品表:shop_items
字段名 | 类型 | 说明 |
---|---|---|
id | bigint | 商品ID |
name | string | 商品名称 |
point_price | int | 积分价格 |
stock | int | 库存(DB中最终库存) |
is_virtual | tinyint | 是否虚拟道具 |
status | int | 是否上架 |
2.3 积分流水表:points_log
字段名 | 类型 | 说明 |
---|---|---|
id | bigint | 主键 |
user_id | bigint | 用户ID |
amount | int | 扣减积分数量(负数) |
type | int | 类型(兑换/签到) |
ref_id | bigint | 关联的订单/任务ID |
created_at | datetime | 创建时间 |
2.4 订单表:shop_orders
字段名 | 类型 | 说明 |
---|---|---|
id | bigint | 主键 |
user_id | bigint | 用户ID |
item_id | bigint | 商品ID |
status | int | 订单状态(0待处理,1处理中,2发货,3完成) |
address | string | 用户收货地址(实物商品) |
created_at | datetime | 下单时间 |
三、Redis 缓存结构设计
为提升响应速度与高并发能力,部分热数据使用 Redis:
3.1 商品库存缓存
redis
Key: shop:item:stock:<item_id>
Type: Integer
用途:高并发下抢兑库存扣减(`DECRBY`)
3.2 用户积分缓存
redis
Key: user:points:<user_id>
Type: Integer
用途:快速判断积分余额,降低 DB 压力
3.3 异常订单回滚队列(zset + TTL)
- Redis ZSET 结构配合定时任务定期扫描超时未支付的兑换记录,自动回退库存+积分。
四、接口调用流程(伪代码)
4.1 商品兑换接口调用链(ThinkPHP 控制器)
php
public function exchange(Request $request)
{
$userId = $request->user()->id;
$itemId = $request->param('item_id');
$num = $request->param('num', 1);
// 校验商品合法性
$item = ShopItem::find($itemId);
if (!$item || $item->status !== 'online') return error('商品不可兑换');
// 校验积分
if (!UserPoints::hasEnough($userId, $item->point_price * $num)) {
return error('积分不足');
}
// Redis 扣减库存
$redisKey = "shop:item:stock:{$itemId}";
if (Redis::decrBy($redisKey, $num) < 0) {
Redis::incrBy($redisKey, $num); // 回滚
return error('库存不足');
}
DB::beginTransaction();
try {
// 1. 扣减积分(写流水)
PointsLog::create([
'user_id' => $userId,
'amount' => -$item->point_price * $num,
'type' => 'exchange',
'ref_id' => 0
]);
UserPoints::decrement('point_balance', $item->point_price * $num);
// 2. 创建订单
$order = ShopOrder::create([
'user_id' => $userId,
'item_id' => $itemId,
'status' => 0
]);
// 3. 异步发货 or 等待人工审核
Queue::push('OrderProcess@handle', ['order_id' => $order->id]);
DB::commit();
return success('兑换成功');
} catch (\Exception $e) {
DB::rollBack();
Redis::incrBy($redisKey, $num); // 回滚库存
return error('兑换失败');
}
}
五、异步订单处理与定时任务(任务调度)
由 Linux 定时任务 + ThinkPHP 脚本完成异步逻辑:
bash
# 每分钟处理队列中的订单状态
* * * * * php think order:dispatch
order:dispatch 示例伪逻辑:
php
public function handle()
{
$orders = ShopOrder::where('status', 0)->limit(10)->get();
foreach ($orders as $order) {
// 如果是虚拟商品,自动发货
if ($order->item->is_virtual) {
VirtualService::deliver($order);
} else {
// 推送到人工发货列表
AdminNotify::send('new_order', $order);
}
$order->status = 2; // 标记为已发货
$order->save();
}
}
六、系统高可用设计建议
方向 | 技术措施 |
---|---|
并发控制 | Redis原子扣减、Redisson锁保证一致性 |
防重复提交 | 接口幂等 Token / 去重操作ID |
流水追踪 | 全部积分变更与库存变更写入日志表 |
限流防刷 | Redis滑动窗口限流、兑换冷却期、风控校验 |
灰度发布 | 商品灰度可见字段 + 白名单控制 |
异常补偿 | MQ失败重试机制、定时任务回滚库存与积分 |
总结
本积分商城系统通过 ThinkPHP 框架构建主服务,配合 Redis 实现高并发处理,MySQL 保持数据主一致性,并通过 MQ/任务调度实现异步处理与容错补偿机制。适配于直播平台高交互、高流量场景,支持实物与虚拟商品灵活拓展,是东莞梦幻网络科技体育直播平台商业闭环中的关键一环。