<?php
class redis_miaoshaControl extends mobileControl
{
public function __construct()
{
parent::__construct();
}
/**
* 接口参数
* @return array
*/
public function getRules()
{
return [
'user_buyOp' => [
'user_id' => ['name' => 'user_id', 'type' => 'int', 'form' => 'get', 'require' => true, 'default' => '', 'desc' => '用户id'],
],
];
}
/**
* 初始化秒杀库存
* @desc 初始化秒杀库存
*/
public function set_storageOp()
{
//redis 初始秒杀库存设置
$ins = \Cache::getInstance('cacheredis');
$goods_storage_data['goods_storage'] = 30;
$ins->hset('goods_storage','nc_', $goods_storage_data);
return_api('初始化秒杀库存');
}
/**
* 初始化令牌桶
* @desc 初始化秒杀库存
*/
public function set_token_bucketOp()
{
//redis 初始秒杀库存设置
$ins = \Cache::getInstance('cacheredis');
$data['num'] = 20;
$ins->hset('token_bucket','nc_', $data);
return_api('初始化令牌桶成功');
}
/**
* 用户购买
* @desc 用户购买
*/
public function user_buyOp()
{
$user_id = $_GET['user_id'];
//用户限流,规定时间内只能请求一次
$ins = \Cache::getInstance('cacheredis');
$user_limit_info = $ins->hget('user_limit' . $user_id,'nc_');
if (!empty($user_limit_info)) {
//上次请求时间
$user_last_time = $user_limit_info['user_last_time'] + 30;
//这里还能优化单位时间内请求次数,只要不超过这个次数,就不更新上次请求时间
$now = time();
//当初操作时间加三十秒,依然大于当前时间,那么就是太频繁
if ($now < $user_last_time) {
error_api('1000021', '请求失败,操作频繁,30秒内无法请求');
}else{
$ins->hset('user_limit' . $user_id,'nc_',['user_last_time' => time()]);
}
} else {
$ins->hset('user_limit' . $user_id,'nc_',['user_last_time' => time()]);
}
//请求消费令牌桶
$token_total = $ins->hget('token_bucket','nc_','num');
if ($token_total <= 0) {
error_api('1000022', '请求失败,当前请求人数太多',[$token_total]);
}
//消费令牌
$token_total -= 1;
$token_bucket['num'] = $token_total;
$ins->hset('token_bucket', 'nc_',$token_bucket);
//判断库存
$storage = $ins->hget('goods_storage','nc_','goods_storage');
if ($storage <= 0) {
error_api('1000023', '请求失败,库存不足',[$storage]);
}
//减少库存
$storage -= 1;
$goods_storage_data['goods_storage'] = $storage;
$ins->hset('goods_storage','nc_', $goods_storage_data);
//加入rabitmq队列,定时脚本消费队列生成订单,发送短信通知用户秒杀成功
$arr['goods_storage'] = $storage;
$arr['token_total'] = $token_total;
return_api('请求成功,订单创建成功会以短信通知',$arr);
}
}
定时脚本生成令牌,根据实际需要控制令牌生成节奏
/** * 增加秒杀令牌 */ private function _cron_create_token_bucket() { $ins = \Cache::getInstance('cacheredis'); //当前令牌数 $token_total = $ins->hget('token_bucket', 'nc_', 'num'); $token_total += 8; //限制峰值 $max = 20; $token_bucket['num'] = $token_total > $max ? $max : $token_total; $ins->hset('token_bucket', 'nc_',$token_bucket); }