-->

PHP资讯

您的当前位置:首页 > 资讯 > redis

redis写一个简单的队列

2020-03-24 22:15:11  来源:admin 点击:822

/**

 * redis队列类

 * Class redisCacher

 * 臧富祥

 */

class redisCacher{

    private static $cacher = null;

    protected $_redis;

    protected $_redis_ip = '127.0.0.1'; //ip

    protected $_redis_port = 6379; //端口

    protected $_redis_db = 0; //数据库号

    protected $_hash_prefix = 'zfx_'; //前缀名称


    public function __construct($ip='',$port='',$db='',$hash_prefix=''){

        if($ip != '') $this->_redis_ip = $ip;

        if($port != '') $this->_redis_port = $port;

        if($db != '') $this->_redis_db = $db;

        if($hash_prefix != '') $this->_hash_prefix = $hash_prefix;

        $this->_redis = new \Redis();

        $this->_redis->connect($this->_redis_ip, $this->_redis_port);

        $this->_redis->select($this->_redis_db);

    }

    public static function getInstance($conf){

        if(self::$cacher == null){self::$cacher = new redisCacher($conf['host'], $conf['port']);}

        return self::$cacher;

    }

    /**

    *入队队列

    */

    public function redisLpush($key,$value)

    {

    $res = $this->_redis->lpush($key,$value);

    return $res;

    }

    /**

    *取出队列

    */

    public function redisRpop($key)

    {

    $res = $this->_redis->rpop($key);

    return $res;

    }

}

/**

*队列

*/

$insert = getCacher()->redisLpush('q1','zfx1');

$insert = getCacher()->redisLpush('q1','zfx2');

$insert = getCacher()->redisLpush('q1','zfx3');

$insert = getCacher()->redisLpush('q1','zfx4');

echo getCacher()->redisRpop('q1');

结果为 zfx1/zfx2/zfx3/zfx4

秒杀系统

 $num = 10;   //系统库存量

 $user_id = $_GET['id'];//当前抢购用户id

 $redis = new Redis();

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

 $len = $redis::llen('zfx:1');  //检查库存,q1 定义为健名

 if($len >= $num)

  echo '已经抢光了哦';

 $result = getCacher()->redisLpush('zfx:1',$user_id);

 if($result)

 echo '恭喜您!抢到了哦';


 //抢购改进版在抢购进行到一定程度,假如现在已经有9个人抢购成功,又来了3个用户同时抢购,这时if条件将会被绕过(条件同时被满足了),这三个用户都能抢购成功。而实际上只剩下一件库存可以抢了。在高并发下,很多看似不大可能是问题的,都成了实际产生的问题了。要解决“超抢/超卖”的问题,核心在于保证检查库存时的操作是依次执行的,再形象的说就是把“多线程”转成“单线程”。即使有很多用户同时到达,也是一个个检查并给与抢购资格,一旦库存抢尽,后面的用户就无法继续了。我们需要使用redis的原子操作来实现这个“单线程”。首先我们把库存存在goods_store:1这个列表中,假设有10件库存,就往列表中push10个数,这个数没有实际意义,仅仅只是代表一件库存。抢购开始后,每到来一个用户,就从goods_store:1中pop一个数,表示用户抢购成功。当列表为空时,表示已经被抢光了。因为列表的pop操作是原子的,即使有很多用户同时到达,也是依次执行的。

抢购的示例代码如下

 $num=10; //库存

 $len=getCacher()::llen('goods_store:1'); //检查库存,goods_store:1 定义为健名

 $count = $num-$len; //实际库存-被抢购的库存 = 剩余可用库存

 for($i=0;$i<$count;$i++)

   getCacher()->redisLpush('goods_store:1',1);//往goods_store列表中,未抢购之前这里应该是默认滴push10个库存数了

 //echo \Redis::llen('goods_store:1');//未抢购之前这里就是10了

//第二步

$user_id =  $_GET['id'];//当前抢购用户id

/* 模拟抢购操作,抢购前判断redis队列库存量 */

$count= getCacher()->redisRpop('goods_store:1');

if(!$count)

  return '已经抢光了哦';

$result = getCacher()->redisLpush('order:1',$user_id);

if($result)

  return '恭喜您!抢到了哦';

操作数据库 /* 下面处理抢购成功流程 */

\DB::table('goods')->decrement('num', 1);//减少num库存字段

相关文章更多 >

© 2024版权所有 水水网

电话:171780793