laravel 礼品码高并发多种实现方法
22652019-05-14 14:39:00返回列表
礼品码在高并发下的多种实现方法,结合laravel框架的实现。
高并发实现礼品码抢购功能方法如下:
一、通过update更新语句会把并发串行化功能实现,通过了压力测试的高并发处理
(假如这N个用户同时到达update这里,这个时候update更新语句会把并发串行化,也就是给同时到达这里的是N个用户排个序,一个一个执行,并生成排他锁)
二、laravel+Redis简单实现队列通过了压力测试的高并发处理
1.先用redis将1000个礼品码缓存
2.然后用redis setnx判断用户key是否已经存在,存在则返回该用户已经参加了,否则继续
3.判断礼品码个数,礼品码没有超出预设
4.更新该礼品码数据用户uid和status状态
不多说,直接上代码:
<?php namespace App\Http\Controllers; use App\Giftcode; use Illuminate\Http\Request; use Illuminate\Routing\Route; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Redis; use Illuminate\Support\Facades\Storage; use PHPUnit\Framework\Exception; class GiftcodeController extends Controller { /** * yun1121.com:方法一: * http://www.xxx.com/api/show1/2 * * 通过update完成高并发更新 * (假如这N个用户同时到达update这里,这个时候update更新语句会把并发串行化,也就是给同时到达这里的是N个用户排个序,一个一个执行,并生成排他锁) * * id为主键 更改主键id为一个唯一的键值,更新时如果主键重复则用try catch 将错误catch 最后返回给用户礼品码 * * ab高并发压力测试语句如下: * ab -n 100 -c 100 -p 'post.txt' -T 'application/x-www-form-urlencoded' 'http://www.xxx.com/api/show1/27' * * @param $uid * @return \Illuminate\Database\Eloquent\Model|null|object|string|static */ public function show1($uid) { try{ $row = DB::update("Update giftcodes set id=:id,status=1,uid=:uid where status=0 and uid is null limit 1 ",['id'=>$uid+10000,'uid'=>$uid]); Log::info('uid:', ['msg'=>'抢购','uid'=>$uid]); }catch (\Exception $e){ $row = 0; Log::info('uid:', ['msg'=>'抢购失败','uid'=>$uid]); } if($row){ $gc_data = DB::table('giftcodes')->where(['id'=> $uid+10000])->first(); $gc_data = (array)$gc_data; return $gc_data['gift_code']; }else{ return 'fail'; } } /** * yun1121.com:方法二: * http://www.xxx.com/api/show2/2 * * 1.先用redis将1000个礼品码缓存 * 2.然后用redis setnx判断用户key是否已经存在,存在则返回该用户已经参加了,否则继续 * 3.判断礼品码个数,礼品码没有超出预设 * 4.更新该礼品码数据用户uid和status状态 * * ab高并发压力测试语句如下: * ab -n 100 -c 100 -p 'post.txt' -T 'application/x-www-form-urlencoded' 'http://www.xxx.com/api/show2/27' * * @param $uid * @return string */ public function show2($uid) { $isqueue = Redis::setnx('userqueue_'.$uid,$uid); if(!$isqueue){ Log::info('uid:', ['msg'=>'您已抢购','uid'=>$uid]); return '您已抢购'; } Log::info('uid:', ['uid'=>$uid]); $giftcode = Redis::rpop('giftcodeslist'); if(!$giftcode){ Log::info('uid:', ['msg'=>'已经购空','uid'=>$uid]); return '已经购空'; } try{ $row = DB::table('giftcodes') ->where('gift_code',"{$giftcode}") ->update(['uid'=>$uid,'status'=> 1]); if($row){ Log::info('uid:', ['msg'=>'抢购成功','uid'=>$uid,'giftcode'=>$giftcode]); return $giftcode; }else{ Redis::del('userqueue_'.$uid); Redis::lpush('giftcodeslist',$giftcode); return 'update fail'; } }catch (\Exception $e){ Redis::del('userqueue_'.$uid,1); Log::info('uid:', ['msg'=>'抢购失败','uid'=>$uid]); Redis::lpush('giftcodeslist',$giftcode); return 'fail'; } } /** * yun1121.com:将礼品码预设到缓存中 * @return string */ public function giftcodeQueue() { Redis::del('giftcodeslist'); $giftcode_list = DB::table('giftcodes')->where(['status'=> 0])->get()->toArray(); if($giftcode_list){ foreach ($giftcode_list as $key=>$val){ $val = (array)$val; Redis::lpush('giftcodeslist',$val['gift_code']); } } return '目前码数:'.Redis::llen('giftcodeslist'); } }
以上代码通过高并发测试成功!
ab -n 100 -c 100 -p 'post.txt' -T 'application/x-www-form-urlencoded' 'http://www.xxx.com/api/show1/27'
欢迎大家讨论提供更多的实现方法!
尊重原创,转载请注明来源 http://www.yun1121.com/study/view/id/175 云逐梦