使用redis实现简单的秒杀
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用redis实现简单的秒杀相关的知识,希望对你有一定的参考价值。
自己做的简单秒杀 感觉思路是没太大问题的 但是代码写的不是很好 做个记录方便以后回来嘲讽下自己
<?php
namespace 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;
}
}
以上是关于使用redis实现简单的秒杀的主要内容,如果未能解决你的问题,请参考以下文章