使用redis实现简单的秒杀

自己做的简单秒杀  感觉思路是没太大问题的  但是代码写的不是很好  做个记录方便以后回来嘲讽下自己

<?phpnamespace frontend\controllers;

use Yii;use frontend\models\Goods;use frontend\models\Order;use yii\web\Controller;

define(‘chenggong‘,1);define(‘yishouwan‘,4);define(‘weidenglu‘,5);

class SeckillController extends Controller{    public function actionIndex()    {        return $this->render(‘index‘);    }

/**     * @return string     */    public function actionSeckill()    {        //获取到前台传来的商品ID及其他信息        $goods_id = yii::$app->request->post(‘gid‘);        //获取当前登录用户ID 如未提示先登录  此处为模拟实现        $user_id = mt_rand(1,100);        if (!$user_id){            return json_encode(weidenglu);        }

//连接redis        $redis = new \Redis();        $redis->connect(‘127.0.0.1‘,6379);        //从redis取出对应商品库存 如不存在 先存        $goods_num = $redis->get(‘goodsNum_‘.$goods_id);        if (!$goods_num){            //在商品被抢完的情况下 也会执行  !$goods_num  即 $goods_num == 0 时  执行  !$goods_num            if ($goods_num === ‘0‘){                return json_encode(yishouwan);            }else{                //去商品库查询库存存入redis链表                $goodsModel =  new Goods();                $goods_num = $goodsModel->find()->select(‘num‘)->where("id = $goods_id")->asArray(true)->one();                 $goods_num = $goods_num[‘num‘] - 1;                //库存减一  执行秒杀                $redis->set(‘goodsNum_‘.$goods_id,$goods_num);                //秒杀成功  订单数据存入redis   后台自动执行添加订单                $info = json_encode([‘user_id‘=>$user_id,‘goods_id‘=>$goods_id]);                $redis->lPush(‘buy_‘.$goods_id,$info);                return json_encode(chenggong);            }        }else{            $goods_num = $redis->decr(‘goodsNum_‘.$goods_id);            if ($goods_num<0){                return json_encode(yishouwan);            }else{                //秒杀成功  订单数据存入redis   后台自动执行添加订单                $info = json_encode([‘user_id‘=>$user_id,‘goods_id‘=>$goods_id]);                $redis->lPush(‘buy_‘.$goods_id,$info);                return json_encode(chenggong);            }        }    }

/*     * 感觉自己这个脚本写的有问题,现在知识有限 ,待以后在升级吧     *      * 此段代码应转入脚本自动后台执行     * 取出队列中的订单信息,并存入数据库     */    public function actionKill()    {        //设置程序开始结束时间  建议以shell脚本开始  程序自动结束        $time1 = ‘2017-05-12 09:18:45‘;        $time2 = ‘2017-05-13 09:18:45‘;        if (time() < strtotime($time1) || time() > strtotime($time2)){            return false;        }        //设置程序最大执行时间 0 为一直执行下去  单位为秒        set_time_limit(0);

$goods_id = 2;        $redis = new \Redis();        $redis->connect(‘127.0.0.1‘,6379);        $goodsModle = new Order();        //从redis中取出相关订单信息        $order = $redis->rPop(‘buy_‘.$goods_id);        if (!$order){            /*             * 如果没有相关信息,等待固定时间后重新执行,             * 或者不等待直接重新执行,一定要有程序结束时间             * 否则程序会一直执行下去,消耗大量资源             *             * 程序最大执行时间为30s ,注意要设置执行时间             *              * 程序调用自己效率会非常慢 , 不推荐 ,待以后改进            */            $this->actionkill();            return false;        }        //生成唯一订单号        $order = $this->object_to_array(json_decode($order));        $order[‘order_no‘] = date(‘YmdHis‘).substr(implode(NULL, array_map(‘ord‘, str_split(substr(uniqid(), 7, 13), 1))), 0, 8);        $order[‘price‘] = 1000;        //订单入库        $goodsModle->add($order);        //此处同上 程序执行结束后继续执行        $this->actionkill();        return true;    }

/**     * 数组 转 对象     *     * @param array $arr 数组     * @return object     */    public function array_to_object($arr)    {        if (gettype($arr) != ‘array‘) {            return;        }        foreach ($arr as $k => $v) {            if (gettype($v) == ‘array‘ || getType($v) == ‘object‘) {                $arr[$k] = (object)array_to_object($v);            }        }        return (object)$arr;    }

/**     * 对象 转 数组     *     * @param object $obj 对象     * @return array     */    public function object_to_array($obj)    {        $obj = (array)$obj;        foreach ($obj as $k => $v) {            if (gettype($v) == ‘resource‘) {                return;            }            if (gettype($v) == ‘object‘ || gettype($v) == ‘array‘) {                $obj[$k] = (array)object_to_array($v);            }        }

return $obj;    }}
时间: 2024-10-29 19:08:34

使用redis实现简单的秒杀的相关文章

利用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部分 ---------------------

基于redis分布式锁实现“秒杀”

最近在项目中遇到了类似"秒杀"的业务场景,在本篇博客中,我将用一个非常简单的demo,阐述实现所谓"秒杀"的基本思路. 业务场景 所谓秒杀,从业务角度看,是短时间内多个用户"争抢"资源,这里的资源在大部分秒杀场景里是商品:将业务抽象,技术角度看,秒杀就是多个线程对资源进行操作,所以实现秒杀,就必须控制线程对资源的争抢,既要保证高效并发,也要保证操作的正确. 一些可能的实现 刚才提到过,实现秒杀的关键点是控制线程对资源的争抢,根据基本的线程知识,可

redis使用watch完成秒杀抢购功能(转)

redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内存数据库来抢购速度极快. 2. 速度快并发自然没不是问题. 3. 使用悲观锁,会迅速增加系统资源. 4. 比队列强的多,队列会使你的内存数据库资源瞬间爆棚. 5. 使用乐观锁,达到综合需求. 我觉得以下代码肯定是你想要的. [php] view plain copy print? <?php hea

基于redis 内存数据库简单使用

在ecplise中使用内存数据的客端户,前提要准备要下载两个jar包 commons-pool2-2.0.jar jedis-2.4.2.jar 前提准备做好了,那我们就开启redis的服务,打开一个命令窗口输入如下命令:redis-server  或redis-server  redis根目\redis.conf 服务器已经开启了,注意端号是6377 2.在eclipse 创建一个项目,把redist需要的包导入项目中 3.写一个Jedis工具类 public class JedisUtil 

Node.js操作Redis的简单示例

Redis是一个key-value类型的数据库,而key全部都是字符串,value可以是集合.hash.list等等. Redis是通过MULTI/DISCARD/EXEC/WATCH这4个命令来实现事务功能.对事务,我们必须知道事务安全性是一个非常重要的. 事务提供了一种"将多个命令打包,然后一次性.按顺序执行"的机制,并且在事务执行期间不会中断--意思就是在事务完成之前,客户端的其他命令都是阻塞状态. var redis = require("redis");

Redis的简单了解以及主从复制

1.Redis的简单了解 Redis是一种高性能的分布式NoSql数据库,持久存储,高并发,数据类型丰富,通过现场申请内存空间,同时可以配置虚拟内存.五种数据类型:string(字符串,这种格式和memcache是一致的).hash(哈希).list(列表,包括队列和栈).set(集合).zset(有序集合),使用key-value对的时候,可以直接存入对象,无需进行序列化,默认的使用了.net中自己的序列化,进行处理,所以也会出现对象循环引用的问题,此时需要使用json.net序列化为字符串,

Redis构建简单的主从复制

Redis构建简单的主从复制 原理: 当设置好slave服务器后,slave会建立和master的连接,然后发送sync命令.无论是第一次同步建立的连接还是连接断开后的重新连 接,master都会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存起来.后台进程完成写文件 后,master就发送文件给slave,slave将文件保存到磁盘上,然后加载到内存恢复数据库快照到slave上. 配置前提,关闭防火墙或允许redis端口通行 Centos7 IP:1

redis使用watch完成秒杀抢购功能

redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内存数据库来抢购速度极快. 2. 速度快并发自然没不是问题. 3. 使用悲观锁,会迅速增加系统资源. 4. 比队列强的多,队列会使你的内存数据库资源瞬间爆棚. 5. 使用乐观锁,达到综合需求. 我觉得以下代码肯定是你想要的. [php] view plain copy print? <?php hea

Redis+lua进行类似秒杀的实现

Redis+lua进行类似秒杀的实现 由于项目需要,需要多线程去获取和修改数据库的库存,考虑到给数据库加锁效率低,所以采用redis+lua来进行实现 . redis的单线程操作特性来执行lua脚本,通过lua脚本来保证原子性.如果通过单纯的redis指令来进行更改,在读和写之间会存在多线程并发更新的问题. 1.首先定义redis数据结构 goodId: { "total":100, "released":0; } 其中goodId为商品id号,可根据此来查询相关的