三种抽奖方式优化总结.md 7.4 KB

三种抽奖方式优化总结

🎯 优化概述

本次优化对消费抽奖营销活动系统进行了重大升级,实现了三种抽奖方式的统一处理流程,提升了系统的可维护性、扩展性和数据一致性。

📊 优化前后对比

优化前

  • 三种抽奖方式各自独立处理
  • 缺乏统一的状态管理
  • 抽奖记录创建时机不一致
  • 难以追溯和管理抽奖状态

优化后

  • 统一的抽奖处理入口
  • 明确的状态流转管理
  • 所有抽奖方式先创建记录再处理
  • 完整的数据追溯链路

🔧 核心优化内容

1. 统一抽奖流程设计

新增统一处理方法

  • handleLotteryByType(): 根据开奖方式分流处理
  • createParticipationRecord(): 统一创建参与记录入口

流程标准化

用户抽奖 → 验证资格 → 消耗机会 → 创建记录 → 根据方式处理 → 更新状态 → 返回结果

2. 抽奖状态管理机制

新增状态枚举

const DRAW_STATUS_PARTICIPATED = 1;     // 已参与(等待开奖)
const DRAW_STATUS_WIN = 2;              // 已中奖
const DRAW_STATUS_NO_WIN = 3;           // 未中奖

状态流转规则

  • 初始状态: 所有抽奖记录创建时状态为"已参与"
  • 结果状态: 开奖后更新为"已中奖"或"未中奖"
  • 异常处理: 发生错误时自动设置为"未中奖"

3. 数据库表结构优化

抽奖记录表新增字段

-- shop_lottery_draw_record 表新增
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '抽奖状态: 1=已参与 2=已中奖 3=未中奖',
`prize_id` int(11) NOT NULL DEFAULT '0' COMMENT '奖品ID,0表示未开奖',

-- 新增索引
KEY `idx_status` (`status`)

机会记录表完善

  • 完善了 shop_lottery_user_chance_record 表结构
  • 优化了字段注释和索引设计

🚀 三种抽奖方式详解

1. 即抽即中 (LOTTERY_TYPE_INSTANT = 1)

新增方法

  • executeInstantDraw(): 执行即抽即中抽奖逻辑

处理流程

createParticipationRecord()     // 创建参与记录
↓
executeInstantDraw()           // 立即执行抽奖
├── 获取可用奖品
├── 执行抽奖算法
├── 减少奖品库存
├── 更新记录状态
├── 创建中奖记录(如果中奖)
├── 自动发放奖品
└── 更新活动统计
↓
返回抽奖结果

优化特点

  • 实时处理,用户体验好
  • 完整的事务控制
  • 详细的错误处理

2. 定时开奖 (LOTTERY_TYPE_TIME = 2)

新增方法

  • handleTimeLottery(): 处理定时抽奖参与
  • processScheduledLotteries(): 定时任务处理入口(公开方法)
  • executeScheduledDraw(): 执行定时开奖
  • executeDrawForRecord(): 为单个记录执行开奖

处理流程

// 用户参与阶段
createParticipationRecord()     // 创建参与记录
↓
handleTimeLottery()            // 处理定时抽奖
├── 验证开奖时间
└── 返回等待状态

// 定时任务阶段
processScheduledLotteries()     // 定时任务入口
├── 查询到期活动
├── executeScheduledDraw()     // 执行定时开奖
│   └── executeDrawForRecord() // 为每个记录开奖
└── 更新活动状态

定时任务配置

# Linux Cron 配置
* * * * * /usr/bin/php /path/to/project/think lottery:process-scheduled

优化特点

  • 批量处理,减少系统压力
  • 公平开奖,所有用户同时处理
  • 支持大型活动的高并发场景

3. 按人数开奖 (LOTTERY_TYPE_PEOPLE = 3)

新增方法

  • handlePeopleLottery(): 处理按人数抽奖

处理流程

createParticipationRecord()     // 创建参与记录
↓
handlePeopleLottery()          // 处理按人数抽奖
├── 查询当前参与人数
├── 检查是否达到开奖人数
├── 如果达标:触发批量开奖
└── 如果不足:返回等待状态

优化特点

  • 事件驱动,人数达标即开奖
  • 增加用户互动和传播效果
  • 实时反馈参与进度

📈 技术优势

1. 架构优势

  • 统一入口: 所有抽奖方式使用相同的处理逻辑
  • 职责分离: 每种方式有专门的处理方法
  • 易于扩展: 新增抽奖方式只需添加对应的处理方法

2. 数据一致性

  • 事务控制: 关键操作使用数据库事务
  • 状态管理: 明确的状态流转规则
  • 错误处理: 完善的异常处理机制

3. 性能优化

  • 批量处理: 定时开奖和按人数开奖支持批量处理
  • 索引优化: 新增状态字段索引提高查询效率
  • 并发控制: 保留分布式锁机制(可选启用)

4. 可维护性

  • 代码复用: 通用逻辑统一处理
  • 清晰结构: 方法职责明确,便于理解
  • 文档完善: 详细的方法注释和文档

🛠 实施步骤

1. 数据库升级

-- 为抽奖记录表添加status字段
ALTER TABLE shop_lottery_draw_record ADD `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '抽奖状态: 1=已参与 2=已中奖 3=未中奖' AFTER `prize_id`;

-- 修改prize_id字段默认值
ALTER TABLE shop_lottery_draw_record MODIFY `prize_id` int(11) NOT NULL DEFAULT '0' COMMENT '奖品ID,0表示未开奖';

-- 添加状态字段索引
ALTER TABLE shop_lottery_draw_record ADD KEY `idx_status` (`status`);

2. 代码部署

  • 部署更新后的 LotteryService.php
  • 部署更新后的 LotteryEnum.php
  • 确保所有相关依赖正常

3. 定时任务配置

# 配置定时任务处理定时开奖
* * * * * /usr/bin/php /path/to/project/think lottery:process-scheduled

4. 测试验证

  • 测试三种抽奖方式的正常流程
  • 验证状态流转的正确性
  • 确认定时任务的正常执行

📋 兼容性说明

向前兼容

  • 保留了原有的方法和接口
  • 现有的抽奖记录数据不受影响
  • 原有的API接口保持兼容

数据迁移

  • 已有的抽奖记录会自动兼容新的状态字段
  • 旧记录的status字段默认为1(已参与)
  • 可根据is_win字段推断实际状态

🔍 监控指标

关键性能指标

  • 各种抽奖方式的响应时间
  • 定时任务的执行效率
  • 状态流转的准确性
  • 数据一致性检查

业务指标

  • 三种抽奖方式的使用分布
  • 用户参与度和中奖率
  • 活动效果对比分析

🎉 预期效果

技术效果

  1. 提升可维护性: 统一的处理流程易于维护和扩展
  2. 增强数据一致性: 明确的状态管理减少数据异常
  3. 改善用户体验: 三种抽奖方式满足不同场景需求
  4. 优化系统性能: 批量处理和索引优化提升性能

业务效果

  1. 活动灵活性: 支持多种抽奖模式适应不同营销策略
  2. 用户参与度: 按人数开奖增加用户互动
  3. 运营效率: 定时开奖适合大型促销活动
  4. 数据分析: 完整的状态记录便于效果分析

📚 相关文档


优化完成时间: 2024年12月 涉及文件: LotteryService.php, LotteryEnum.php, 相关文档 测试状态: 待测试 上线状态: 待部署