当前位置:首页 > PHP

php 抢购实现

2026-02-13 16:27:42PHP

抢购系统设计要点

高并发抢购系统的核心在于解决超卖、性能瓶颈和数据一致性问题。PHP实现需结合数据库、缓存和队列技术。

数据库层面优化

使用InnoDB引擎的事务和行级锁确保数据一致性。创建商品表时预留库存字段:

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

悲观锁实现方式:

$pdo->beginTransaction();
$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();
}

乐观锁实现

通过版本号控制并发:

$version = $pdo->query("SELECT version FROM seckill_goods WHERE id=$goods_id")->fetchColumn();
$affected = $pdo->exec("UPDATE seckill_goods SET stock=stock-1, version=version+1 
                       WHERE id=$goods_id AND version=$version");
if($affected > 0){
    // 抢购成功
}

Redis原子操作

使用Redis的DECR和Lua脚本保证原子性:

php 抢购实现

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$script = "
    local stock = tonumber(redis.call('GET', KEYS[1]))
    if stock > 0 then
        redis.call('DECR', KEYS[1])
        return 1
    end
    return 0
";
$result = $redis->eval($script, ["goods_stock:$goods_id"], 1);

消息队列削峰

使用RabbitMQ或Redis List处理瞬时流量:

// 生产者
$redis->lPush('seckill_queue', json_encode(['user_id'=>$user_id, 'goods_id'=>$goods_id]));

// 消费者
while(true){
    $data = json_decode($redis->rPop('seckill_queue'), true);
    processOrder($data['user_id'], $data['goods_id']);
}

限流措施

使用Redis实现令牌桶限流:

function isAllowed($user_id){
    $key = "rate_limit:$user_id";
    $redis->multi()
          ->set($key, 10, ['NX', 'EX'=>60])
          ->decr($key)
          ->exec();
    return $redis->get($key) >= 0;
}

缓存预热

活动开始前将库存加载到Redis:

php 抢购实现

$stock = $pdo->query("SELECT stock FROM seckill_goods WHERE id=$goods_id")->fetchColumn();
$redis->set("goods_stock:$goods_id", $stock);

防脚本作弊

增加验证码机制:

// 生成验证码
$code = substr(md5(mt_rand()), 0, 4);
$_SESSION['seckill_code'] = $code;

// 校验验证码
if($_POST['code'] != $_SESSION['seckill_code']){
    die('验证码错误');
}

服务层优化

使用Swoole等常驻内存框架提升PHP性能:

$http = new Swoole\Http\Server("0.0.0.0", 9501);
$http->on('request', function ($request, $response) {
    $response->header("Content-Type", "text/plain");
    $response->end(handleSeckill());
});
$http->start();

数据一致性最终检查

通过定时任务核对Redis与数据库数据:

$redis_stock = $redis->get("goods_stock:$goods_id");
$db_stock = $pdo->query("SELECT stock FROM seckill_goods WHERE id=$goods_id")->fetchColumn();
if($redis_stock != $db_stock){
    // 触发报警并修复数据
}

标签: php
分享给朋友:

相关文章

php实现购物车

php实现购物车

PHP实现购物车功能 购物车功能是电商网站的核心模块之一,通常涉及商品添加、删除、数量修改和结算等操作。以下是使用PHP实现购物车功能的几种方法。 使用Session存储购物车数据 Session是…

php长连接实现

php长连接实现

PHP 长连接实现方法 长连接(Keep-Alive)允许客户端与服务器在一次TCP连接中发送和接收多个HTTP请求/响应,减少重复建立连接的开销。以下是PHP中实现长连接的几种方式: 配置HTTP…

php 购物车实现

php 购物车实现

数据库设计 购物车功能通常需要设计数据库表存储商品和用户信息。常见的表包括products(商品表)、users(用户表)和cart(购物车表)。cart表通常包含字段:id(主键)、user_id(…

php实现下载

php实现下载

PHP实现文件下载 使用PHP实现文件下载可以通过设置HTTP头部信息强制浏览器下载文件而非直接打开。以下是几种常见的方法: 方法一:直接输出文件内容 $file_path = 'path/to/…

php实现登陆

php实现登陆

PHP 实现登录功能 创建登录表单 在 HTML 文件中创建一个登录表单,包含用户名和密码输入框,表单的 action 属性指向处理登录的 PHP 文件。 <form action="logi…

php实现定时

php实现定时

PHP 实现定时任务的方法 PHP 本身是脚本语言,通常需要借助外部工具或框架实现定时任务。以下是几种常见方法: 使用 Cron 任务 Linux 系统自带的 Cron 是常用的定时任务工具。通过编…