利用redis List队列简单实现秒杀 PHP代码实现

利用redis List队列简单实现秒杀 PHP代码实现

2018年05月28日 11:37:46 m_nanle_xiaobudiu 阅读数 35674更多

分类专栏: Redis

版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/m_nanle_xiaobudiu/article/details/80479666

一 生产者producer部分

--------------------------------producer 部分注释------------------------------------------------------------

用户在页面请求之后, 获取到用户uid , 跳转到这个加入队列的方法 (这里直接在producer中模拟了多个uid)

在方法内部判断redis队列长度是否已经达到要求, 如果没有超出, 则执行加入队列的操作 (这里为了简洁,没有封装成方法)

注: producer.php没有进行数据库的操作,只有接受uid和其他值的操作, 数据库操作一律放在消费者consumer.php中

--------------------------------producer 注释结束-----------------------------------------------------------------------

生产者代码 producer.php:

  1. <?php

  2.  

  3.  

    //连接redis数据库

  4.  

    $redis = new Redis();

  5.  

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

  6.  

    $redis_name = ‘secKill3‘;

  7.  

  8.  

    //模拟100人请求秒杀(高压力)

  9.  

    for ($i = 0; $i < 100; $i++) {

  10.  

    $uid = rand(10000000, 99999999);

  11.  

    //获取当前队列已经拥有的数量,如果人数少于十,则加入这个队列

  12.  

    $num = 10;

  13.  

    if ($redis->lLen($redis_name) < $num) {

  14.  

    $redis->rPush($redis_name, $uid);

  15.  

    echo $uid . "秒杀成功"."<br>";

  16.  

    } else {

  17.  

    //如果当前队列人数已经达到10人,则返回秒杀已完成

  18.  

    echo "秒杀已结束<br>";

  19.  

    }

  20.  

    }

  21.  

    //关闭redis连接

  22.  

    $redis->close();

  23.  

注: 执行完producer.php文件,本地redis数据库第0号数据库中应该有一个键名为"secKill3"的List队列,像这样

二 消费者consumer部分

------------------------------消费者部分注释---------------------------------------------

消费者一直读取redis数据库中指定队列,一有值,立即取出,并进行相应数据库操作

------------------------------消费者部分注释结束----------------------------------------

消费者代码 consumer.php

  1. <?php

  2.  

  3.  

    //设置redis数据库连接及键名

  4.  

    $redis = new Redis();

  5.  

    $redis->connect(‘127.0.0.1‘);

  6.  

    $key = ‘secKill3‘;//redis数据库key [注:默认redis数据库选择第0号数据库]

  7.  

  8.  

    //PDO连接mysql数据库

  9.  

    $dsn = "mysql:dbname=test;host=127.0.0.1";

  10.  

    $pdo = new PDO($dsn, ‘root‘, ‘123456‘);

  11.  

  12.  

    //死循环

  13.  

    //从队列最前头取出一个值,判断这个值是否存在,取出时间和uid,保存到数据库

  14.  

    //数据库插入失败时,要有回滚机制

  15.  

    //注: rpush 和lpop是一对

  16.  

  17.  

    while(1) {

  18.  

    //从队列最前头取出一个值

  19.  

    $uid = $redis->lPop($key);

  20.  

    //判断值是否存在

  21.  

    if(!$uid || $uid == ‘nil‘){

  22.  

    sleep(2);

  23.  

    continue;

  24.  

    }

  25.  

    //生成订单号

  26.  

    $orderNum = build_order_no($uid);

  27.  

    //生成订单时间

  28.  

    $timeStamp = time();

  29.  

    //构造插入数组

  30.  

    $user_data = array(‘uid‘=>$uid,‘time_stamp‘=>$timeStamp,‘order_num‘=>$orderNum);

  31.  

    //将数据保存到数据库

  32.  

    $sql = "insert into student (uid,time_stamp,order_num) values (:uid,:time_stamp,:order_num)";

  33.  

    $stmt = $pdo->prepare($sql);

  34.  

    $res = $stmt->execute($user_data);

  35.  

    //数据库插入数据失败,回滚

  36.  

    if(!$res){

  37.  

    $redis->rPush($key,$uid);

  38.  

    }

  39.  

    }

  40.  

  41.  

    //生成唯一订单号

  42.  

    function build_order_no($uid){

  43.  

    return substr(implode(NULL, array_map(‘ord‘, str_split(substr(uniqid(), 7, 13), 1))), 0, 8).$uid;

  44.  

    }

注: 执行完consumer.php之后,数据库对应数据表应该有数值

到此,秒杀结束

备注:

用到的student数据表结构sql

  1. CREATE TABLE `student` (

  2.  

    `uid` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT ‘uid‘,

  3.  

    `username` varchar(20) NOT NULL DEFAULT ‘‘,

  4.  

    `time_stamp` int(11) NOT NULL DEFAULT 0,

  5.  

    `order_num` bigint(20) UNSIGNED NOT NULL DEFAULT 0,

  6.  

    PRIMARY KEY (`uid`) USING BTREE,

  7.  

    key (time_stamp)

  8.  

    ) ENGINE = MyISAM default charset=utf8;

 

原文地址:https://www.cnblogs.com/guiyishanren/p/11563862.html

时间: 2024-11-02 23:37:26

利用redis List队列简单实现秒杀 PHP代码实现的相关文章

redis消息队列简单应用

参考 https://blog.yxccan.cn/blog/detail/3 一.什么是消息队列 是一个消息的链表,是一个异步处理的数据处理引擎. PS:可以理解为在redis的list列表中存放消息数据,然后按照排队方式先进先出(左进右出:右进左出) 二.可以使用的应用场景 主要应用一些延迟或异步操作的场景比如:发送邮件.发送短信.视频转码.图片转码.日志存储.导入数据等在发送邮件或者短信,我们不希望程序一直停留,等待发送成功才相应,而是异步进行处理,即:将待发送的邮件数据添加到消息队列中,

用redis做一个简单的秒杀

下面是一个简单的下单操作 <?php include "MMysql.class.php"; $configArr=[ 'host'=>, 'port'=>, 'user'=>, 'passwd'=>, 'dbname'=>, ]; $db = new MMysql($configArr); $sql="select * from sdb_b2c_products where product_id='38'"; $product=

(转)java redis使用之利用jedis实现redis消息队列

应用场景 最近在公司做项目,需要对聊天内容进行存储,考虑到数据库查询的IO连接数高.连接频繁的因素,决定利用缓存做. 从网上了解到redis可以对所有的内容进行二进制的存储,而java是可以对所有对象进行序列化的,序列化的方法会在下面的代码中提供实现. 序列化 这里我编写了一个java序列化的工具,主要是对对象转换成byte[],和根据byte[]数组反序列化成java对象: 主要是用到了ByteArrayOutputStream和ByteArrayInputStream: 需要注意的是每个自定

Java利用Redis实现消息队列

应用场景 为什么要用redis?二进制存储.java序列化传输.IO连接数高.连接频繁 一.序列化 这里编写了一个java序列化的工具,主要是将对象转化为byte数组,和根据byte数组反序列化成java对象; 主要是用到了ByteArrayOutputStream和ByteArrayInputStream; 注意:每个需要序列化的对象都要实现Serializable接口; 其代码如下: 1 package Utils; 2 import java.io.*; 3 /** 4 * Created

java redis使用之利用jedis实现redis消息队列

应用场景 对于数据库查询的IO连接数高.连接频繁的情况,可以考虑使用缓存实现. 从网上了解到redis可以对所有的内容进行二进制的存储,而java是可以对所有对象进行序列化的,序列化的方法会在下面的代码中提供实现. 序列化 这里我编写了一个java序列化的工具,主要是对对象转换成byte[],和根据byte[]数组反序列化成java对象: 主要是用到了ByteArrayOutputStream和ByteArrayInputStream: 需要注意的是每个自定义的需要序列化的对象都要实现Seria

Redis消息队列

一般来说,消息队列有两种场景,一种是发布者订阅者模式,一种是生产者消费者模式.利用redis这两种场景的消息队列都能够实现. 生产者消费者模式:生产者生产消息放到队列里,多个消费者同时监听队列,谁先抢到消息谁就会从队列中取走消息:即对于每个消息只能被最多一个消费者拥有: 发布者订阅者模式:发布者生产消息放到队列里,多个监听队列的消费者都会收到同一份消息:即正常情况下每个消费者收到的消息应该都是一样的: 对应的使用场景包括:A系统向队列中存放数据:B系统在队列中取数据: 1.redis队列模式:可

Redis之个人简单理解

1.什么是redis? 在过去的几年中,NoSQL数据库一度成为高并发.海量数据存储解决方案的代名词,与之相应的产品也呈现出雨后春笋般的生机.然而在众多产品中能够脱颖而出的却屈指可数,如Redis.MongoDB.BerkeleyDB和CouchDB等.由于每种产品所拥有的特征不同,因此它们的应用场景也存在着一定的差异,下面仅给出简单的说明:      1). BerkeleyDB是一种极为流行的开源嵌入式数据库,在更多情况下可用于存储引擎,比如BerkeleyDB在被Oracle收购之前曾作为

redis缓存队列+MySQL +php任务脚本定时批量入库

原文地址:http://blog.jobbole.com/99567/ 需求背景:有个调用统计日志存储和统计需求,要求存储到mysql中:存储数据高峰能达到日均千万,瓶颈在于直接入库并发太高,可能会把mysql干垮. 问题分析 思考:应用网站架构的衍化过程中,应用最新的框架和工具技术固然是最优选择:但是,如果能在现有的框架的基础上提出简单可依赖的解决方案,未尝不是一种提升自我的尝试.解决: 问题一:要求日志最好入库:但是,直接入库mysql确实扛不住,批量入库没有问题,done.[批量入库和直接

利用redis setbit和bitmap统计用户数

公司的统计系统接到一个需求,统计时间段内发生过某行为的用户总数.并且时间段的长度是可变的.公司业务用户数量巨大,而且统计系统是实时统计,所以数据的存储.计算效率都需要一个比较好的方案.下面是互联网上的一篇文章,利用redis bitmap. getspool.com的重要统计数据是实时计算的.Redis的bitmap让我们可以实时的进行类似的统计,并且极其节省空间.在模拟1亿2千8百万用户的模拟环境下,在一台MacBookPro上,典型的统计如“日用户数”(dailyunique users)