当前位置:首页 > PHP

php 实现秒杀功能

2026-02-15 08:33:18PHP

PHP实现秒杀功能的核心要点

秒杀场景的特点是高并发、低库存,需解决超卖、性能瓶颈、恶意请求等问题。以下是关键实现方案:

数据库设计优化

使用InnoDB引擎,利用事务和行锁保证数据一致性。商品表需包含stock字段(无符号整型)并设置乐观锁版本号:

CREATE TABLE `seckill_goods` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `stock` int(11) unsigned NOT NULL COMMENT '剩余库存',
  `version` int(11) unsigned DEFAULT 0 COMMENT '乐观锁版本号',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

悲观锁方案(MySQL行锁)

通过SELECT ... FOR UPDATE锁定记录,适合并发量中等场景:

$pdo->beginTransaction();
try {
    $stmt = $pdo->prepare("SELECT stock FROM seckill_goods WHERE id = ? FOR UPDATE");
    $stmt->execute([$goods_id]);
    $stock = $stmt->fetchColumn();

    if ($stock > 0) {
        $pdo->prepare("UPDATE seckill_goods SET stock = stock - 1 WHERE id = ?")->execute([$goods_id]);
        $pdo->commit();
        echo "秒杀成功";
    } else {
        $pdo->rollBack();
        echo "库存不足";
    }
} catch (Exception $e) {
    $pdo->rollBack();
    echo "系统异常";
}

乐观锁方案

通过版本号避免阻塞,适合高并发场景:

$pdo->beginTransaction();
try {
    // 先查询当前版本号
    $stmt = $pdo->prepare("SELECT stock, version FROM seckill_goods WHERE id = ?");
    $stmt->execute([$goods_id]);
    $data = $stmt->fetch(PDO::FETCH_ASSOC);

    if ($data['stock'] > 0) {
        // 带版本号更新
        $affected = $pdo->prepare("UPDATE seckill_goods SET stock = stock - 1, version = version + 1 
                                  WHERE id = ? AND version = ?")->execute([$goods_id, $data['version']]);

        if ($affected) {
            $pdo->commit();
            echo "秒杀成功";
        } else {
            $pdo->rollBack();
            echo "请重试";
        }
    } else {
        $pdo->rollBack();
        echo "库存不足";
    }
} catch (Exception $e) {
    $pdo->rollBack();
    echo "系统异常";
}

Redis原子操作

利用Redis的DECRWATCH实现原子减库存:

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis_key = "seckill:goods:$goods_id";

// 监控库存键
$redis->watch($redis_key);
$stock = $redis->get($redis_key);

if ($stock > 0) {
    $redis->multi();
    $redis->decr($redis_key);
    $result = $redis->exec();

    if ($result) {
        echo "秒杀成功";
        // 异步更新数据库
    } else {
        echo "请重试";
    }
} else {
    $redis->unwatch();
    echo "库存不足";
}

流量削峰策略

  1. 前端限流:按钮倒计时+随机延迟提交
  2. 令牌桶算法:使用Redis实现请求速率限制
  3. 消息队列:将请求写入RabbitMQ/Kafka异步处理
// Redis令牌桶示例
$rate_limit_key = "user_limit:$user_id";
$limit = 10; // 每秒10次

if ($redis->lLen($rate_limit_key) < $limit) {
    $redis->lPush($rate_limit_key, time());
    $redis->expire($rate_limit_key, 1);
    // 处理请求
} else {
    echo "操作过于频繁";
}

防刷机制

  1. 隐藏秒杀接口:动态生成URL
  2. 验证码验证:复杂图形验证码
  3. 用户限购:Redis记录用户购买记录
  4. IP限制:Nginx层限制单IP访问频率

分层缓存架构

  1. Nginx缓存:静态页面缓存
  2. Redis集群:库存预热+热点数据缓存
  3. 数据库分库分表:降低单表压力

注意事项

  • 压测工具:使用JMeter模拟10万级并发测试
  • 库存预热:活动开始前将库存加载到Redis
  • 超时处理:设置合理的PHP脚本执行时间
  • 降级方案:库存售罄后直接返回静态页

实际部署时需根据业务规模选择组合方案,分布式环境需考虑Redis集群和分布式锁的实现。

php 实现秒杀功能

标签: 功能秒杀
分享给朋友:

相关文章

前端实现拖拽功能vue

前端实现拖拽功能vue

实现拖拽功能的基本方法 在Vue中实现拖拽功能可以通过HTML5的拖放API或第三方库如vuedraggable来完成。HTML5的拖放API提供了原生支持,而vuedraggable则简化了列表拖拽…

vue实现名字查找功能

vue实现名字查找功能

Vue 实现名字查找功能 在 Vue 中实现名字查找功能,可以通过以下方法完成。这里假设有一个名字列表,需要根据用户输入的关键词进行筛选。 数据准备 在 Vue 的 data 中定义名字列表和搜索…

php实现打印功能

php实现打印功能

PHP实现打印功能的方法 在PHP中实现打印功能可以通过多种方式完成,包括直接输出到浏览器、生成PDF文件、调用打印机接口等。以下是几种常见的方法: 直接输出HTML内容 PHP可以通过echo或…

vue 实现筛选功能

vue 实现筛选功能

实现筛选功能的基本思路 在Vue中实现筛选功能通常涉及以下几个核心步骤:数据绑定、筛选逻辑处理、结果展示。以下是具体实现方法。 数据准备与绑定 准备一个包含所有数据的数组,并使用v-model或v-…

php怎么实现登录功能

php怎么实现登录功能

数据库准备 创建用户表存储登录信息,通常包括用户名、密码(需加密)等字段。示例SQL: CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY…

vue实现答题功能

vue实现答题功能

Vue实现答题功能 数据准备 创建一个包含题目、选项和正确答案的数据结构,通常是一个数组对象。每个题目对象包含问题文本、选项数组和正确答案索引。 const questions = [ {…