当前位置:首页 > PHP

php redis实现秒杀

2026-03-13 09:19:53PHP

Redis实现秒杀的PHP方案

秒杀场景的核心问题是高并发下的超卖和性能瓶颈。Redis凭借单线程原子性和高性能特性,是解决这一问题的理想选择。以下是基于PHP和Redis的完整实现方案:

使用Redis原子操作防止超卖

通过Redis的原子性操作(如DECR、INCRBY)确保库存扣减的准确性:

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$productId = 'product_123';
$userId = uniqid();

// Lua脚本保证原子性
$lua = <<<LUA
local stock = tonumber(redis.call('GET', KEYS[1]))
if stock > 0 then
    redis.call('DECR', KEYS[1])
    return redis.call('SADD', KEYS[2], ARGV[1])
end
return 0
LUA;

$result = $redis->eval($lua, [$productId, 'seckill_success_users', $userId], 2);
if ($result) {
    echo "秒杀成功";
} else {
    echo "秒杀失败";
}

库存预热与限流措施

提前将商品库存加载到Redis,避免活动开始时的数据库压力:

// 活动开始前执行
$totalStock = 1000;
$redis->set('product_123', $totalStock);
$redis->expire('product_123', 3600); // 设置过期时间

结合令牌桶算法实现限流:

function acquireToken($redis, $key, $limit, $expire) {
    $now = microtime(true);
    $redis->watch($key);
    $lastTime = $redis->get($key);

    if ($lastTime && $now - $lastTime < 1/$limit) {
        $redis->unwatch();
        return false;
    }

    $redis->multi();
    $redis->set($key, $now);
    $redis->expire($key, $expire);
    return $redis->exec();
}

异步订单处理方案

秒杀成功后采用消息队列异步处理订单:

// 秒杀成功后
if ($result) {
    $orderData = [
        'user_id' => $userId,
        'product_id' => $productId,
        'create_time' => time()
    ];
    $redis->lPush('seckill_order_queue', json_encode($orderData));
}

后台消费进程处理:

while (true) {
    $orderJson = $redis->rPop('seckill_order_queue');
    if ($orderJson) {
        $order = json_decode($orderJson, true);
        // 实际订单入库操作
        saveToDatabase($order);
    }
    usleep(100000); // 100ms间隔
}

数据一致性保障

采用双重检查避免数据库与Redis数据不一致:

// 下单前再次检查
if ($redis->sIsMember('seckill_success_users', $userId)) {
    $dbStock = getDbStock($productId);
    if ($dbStock > 0) {
        createOrder($userId, $productId);
    } else {
        $redis->sRem('seckill_success_users', $userId);
        $redis->incr('product_123'); // 回滚库存
    }
}

性能优化关键点

  1. 使用Redis管道减少网络往返:

    $redis->pipeline();
    $redis->get('stock');
    $redis->sAdd('users', $userId);
    $results = $redis->exec();
  2. 连接池管理避免频繁创建连接

  3. 热点数据分片存储减轻单节点压力

  4. 采用CLUSTER模式实现横向扩展

    php  redis实现秒杀

该方案通过Redis原子操作保证数据一致性,异步处理提升系统吞吐量,多重校验确保最终准确性,可支持万级QPS的秒杀场景。实际部署时需要根据具体业务调整参数并进行压力测试。

标签: 秒杀php
分享给朋友:

相关文章

php实现分页

php实现分页

PHP实现分页的基本方法 使用原生PHP实现分页功能需要结合数据库查询和HTML展示。以下是核心实现步骤: 数据库查询与分页逻辑 // 连接数据库 $conn = new mysqli('loca…

php 路由实现

php 路由实现

PHP 路由实现方法 在 PHP 中实现路由功能有多种方式,以下是几种常见的实现方法: 使用原生 PHP 实现 通过解析 URL 并匹配对应的控制器和动作: $request = $_SERVER…

php验证码的实现

php验证码的实现

PHP 验证码实现方法 使用 GD 库生成基础验证码 创建画布并生成随机字符串作为验证码内容: session_start(); $width = 120; $height = 40; $image…

php实现跳转

php实现跳转

PHP 实现页面跳转的方法 在 PHP 中实现页面跳转有多种方式,以下是常见的几种方法及其适用场景: 使用 header() 函数 通过 header() 函数发送 HTTP 头部信息实现跳转。注意…

php实现统计

php实现统计

PHP 实现统计功能 在 PHP 中实现统计功能通常涉及数据的收集、处理和展示。以下是一些常见的统计实现方法: 数据库数据统计 通过 SQL 查询可以直接从数据库中获取统计结果: $conn =…

php 实现单点登录

php 实现单点登录

PHP 实现单点登录的方法 单点登录(SSO)允许用户通过一次登录访问多个相互信任的系统。以下是基于 PHP 的实现方案: 基于共享 Session 的方案 在同一个主域名下的子域名间可以通过共享…