laravel基于redis实现的一个简单的秒杀系统

说明:网上很多redis秒杀系统的文章,看的都是一头雾水,然后自己来实现一个,也方便以后自己学习

实现的方式是用的redis的list队列,框架为laravel

核心部分为list的pop操作,此操作为原子性,即使很多用户同时到达,也是依次执行

 

示例:

<?php
/**
 * Created by PhpStorm.
 * User: chenyRain
 * Date: 2018/5/28
 * Time: 11:36
 */

namespace App\Http\Controllers;


use Illuminate\Support\Facades\Redis;

class RedisController extends Controller
{
    public $user_number = 50; // 允许进入队列的人数

    /**
     * 这个方法,相当于点击进入商品详情页,开启秒杀活动
     */
    public function index()
    {
        $goods_number = 10; // 商品库存数量为10

        if (! empty(Redis::llen('goods_name'))) {
            echo '已经设置了库存了';
            exit;
        }

        // 初始化
        Redis::command('del', ['user_number', 'success']);

        // 将商品存入redis链表中
        for ($i = 1; $i <= $goods_number; $i++) {

            // lpush从链表头部添加元素
            Redis::lpush('goods_name', $i);
        }

        // 设置过期时间
        $this->setTime();

        // 返回链表 goods_name 的长度
        echo '商品存入队列成功,数量:'.Redis::llen('goods_name');
    }

    public function setTime()
    {
        // 设置 goods_name 过期时间,相当于活动时间
        Redis::expire('goods_name', 120);
    }


    /**
     * 这个方法,相当于点击 抢购 操作
     */
    public function start()
    {
        $uid = mt_rand(1, 99); // 假设用户ID

        // 如果人数超过50,直接提示被抢完
        if (Redis::llen('user_number') > $this->user_number) {
            echo '遗憾,被抢完了';
            exit;
        }

        // 获取抢购结果,假设里面存了uid
        $result = Redis::lrange('success', 0, 20);
        // 如果有一个用户只能抢一次,可以加上下面判断
        if (in_array($uid, $result)) {
            echo '你已经抢过了';
            exit;
        }

        // 将用户加入队列中
        Redis::lpush('user_number', $uid);

        // 从链表的头部删除一个元素,返回删除的元素,因为pop操作是原子性,即使很多用户同时到达,也是依次执行
        $count = Redis::lpop('goods_name');
        if (! $count) {
            echo '被抢完了';
            exit;
        }

        $msg = '抢到的人为:'.$uid.',商品ID为:'.$count;
        Redis::lpush('success', $msg);
        echo '公司拟,抢到了';
    }

    /**
     * 查看抢到结果
     */
    public function result()
    {
        $result = Redis::lrange('success', 0, 20);
        dd($result);
    }
}

说明一下:

  1、首先运行index方法设置商品库存,并初始化结果队列和用户队列

  2、运行start方法来抢购

下面配上ab测试结果

附上抢到的人名单

 

转载于:https://www.cnblogs.com/chenhaoyu/p/9100641.html

Laravel 中使用 Redis 实现锁非常简单,可以使用 Redis 提供的 setnx 命令实现。setnx 命令可以将一个 key 的值设为 value,当且仅当该 key 不存在,如果该 key 已经存在,则 setnx 命令不做任何操作。 以下是一个简单Redis实现的示例代码: ```php use Illuminate\Support\Facades\Redis; class RedisLock { protected $redis; protected $lockKey; protected $timeout; protected $expire; /** * RedisLock constructor. * * @param string $lockKey 用于获取锁的 key * @param int $timeout 获取锁的超时时间,单位是毫秒 * @param int $expire 锁的过期时间,单位是秒 */ public function __construct($lockKey, $timeout = 3000, $expire = 60) { $this->redis = Redis::connection(); $this->lockKey = $lockKey; $this->timeout = $timeout; $this->expire = $expire; } /** * 获取锁 * * @return bool */ public function acquire() { $timeoutAt = microtime(true) + $this->timeout / 1000; while (microtime(true) < $timeoutAt) { $result = $this->redis->setnx($this->lockKey, time() + $this->expire); if ($result) { return true; } usleep(1000); } return false; } /** * 释放锁 */ public function release() { $lockExpire = $this->redis->get($this->lockKey); if ($lockExpire > time()) { $this->redis->del($this->lockKey); } } } ``` 在使用该类时,可以这样调用: ```php $redisLock = new RedisLock('lock_key', 5000, 60); if ($redisLock->acquire()) { // 获取锁成功 // 执行业务逻辑 $redisLock->release(); } else { // 获取锁失败 // 执行失败处理逻辑 } ``` 在上面的代码中,$lockKey 是用于获取锁的 key,$timeout 是获取锁的超时时间,单位是毫秒,$expire 是锁的过期时间,单位是秒。acquire 方法用于获取锁,如果获取成功则返回 true,否则返回 false。release 方法用于释放锁。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值