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