* 构造
*
* @return MyPDO*/
private function __construct($dbHost, $dbUser, $dbPasswd, $dbName, $dbCharset) {try{$this->dsn = ‘mysql:host=‘.$dbHost.‘;dbname=‘.$dbName;$this->dbh = new PDO($this->dsn, $dbUser, $dbPasswd);$this->dbh->exec(‘SET character_set_connection=‘.$dbCharset.‘, character_set_results=‘.$dbCharset.‘, character_set_client=binary‘);
}catch (PDOException $e) {exit($e->getMessage());
}
}/**
* 防止克隆
**/
private function__clone() {
}/**
* Singleton instance
*
* @return Object*/
public static function getInstance($dbHost, $dbUser, $dbPasswd, $dbName, $dbCharset) {if (self::$_instance === null) {
self::$_instance = new self($dbHost, $dbUser, $dbPasswd, $dbName, $dbCharset);
}return self::$_instance;
}/**
* Query 查询*/
public function query($strSql, $queryMode = ‘All‘, $debug = false) {if ($debug === true) $this->debug($strSql);$recordset = $this->dbh->query($strSql);if ($recordset) {$recordset->setFetchMode(PDO::FETCH_ASSOC);if ($queryMode == ‘All‘) {$result = $recordset->fetchAll();
}elseif ($queryMode == ‘Row‘) {$result = $recordset->fetch();
}
}else{$result = null;
}return $result;
}/**
* Insert 插入*/
public function insert($table, $arrayDataValue, $debug = false) {$strSql = "INSERT INTO `$table` (`".implode(‘`,`‘, array_keys($arrayDataValue))."`) VALUES (‘".implode("‘,‘", $arrayDataValue)."‘)";if ($debug === true) $this->debug($strSql);$result = $this->dbh->exec($strSql);return $result;
}/**
* 执行语句*/
public function execSql($strSql, $debug = false) {if ($debug === true) $this->debug($strSql);$result = $this->dbh->exec($strSql);return $result;
}/**
* debug
*
* @param mixed $debuginfo*/
private function debug($debuginfo) {var_dump($debuginfo);exit();
}
}classTest {private static $instance = null;//用单列模式 实例化Redis
public static functionRedis() {if (self::$instance == null) {$redis=newRedis();$redis->connect(‘127.0.0.1‘,6379);
self::$instance = $redis;
}return self::$instance;
}public function getOne($sql) {$db = MyPDO::getInstance(‘localhost‘, ‘root‘, ‘168168‘, ‘test‘, ‘utf8‘);$data = $db->query($sql)[0];return $data;
}public function exec($sql) {$db = MyPDO::getInstance(‘localhost‘, ‘root‘, ‘168168‘, ‘test‘, ‘utf8‘);return $db->execSql($sql);
}public function insert($table,$data) {$db = MyPDO::getInstance(‘localhost‘, ‘root‘, ‘168168‘, ‘test‘, ‘utf8‘);return $db->insert($table,$data);
}//将商品库存循环到lpush的num里
public functiondoPageSaveNum() {$redis=self::Redis();$goods_id=1;$sql="select id, num,money from ims_hotmallstore_goods where id=".$goods_id;$goods = $this->getOne($sql);//print_r($goods);die;
if(!empty($goods[‘num‘])) {for ($i=1; $i<=$goods[‘num‘]; $i++) {$redis->lpush(‘num‘,$i);
}die(‘成功!库存数:‘.$goods[‘num‘]);
}else{die(‘数据库已无库存‘);
}
}//抢购下单
public functiondoPageGoodsStore() {$redis=self::Redis();$goods_id=1;$user_id = mt_rand(1,100);if ($redis->sismember(‘user_list_‘.$goods_id,$user_id)) {echo ‘已下单‘;return false;
;
}$count=$redis->rpop(‘num‘);//每次从num取出1,防止超卖
if($count==0) {$this->echoMsg(0,‘已无库存‘);
}//加入已购买用户集合,防止重复购买
$redis->sAdd(‘user_list_‘.$goods_id,$user_id);$sql="select id, num, money from ims_hotmallstore_goods where id=".$goods_id;$goods = $this->getOne($sql);$this->doPageGoodsOrder($user_id,$goods,1);
}public functionorderNo() {return date(‘ymd‘).substr(implode(NULL, array_map(‘ord‘, str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}//下单更新库存
public function doPageGoodsOrder($user_id,$goods,$goods_number) {$orderNo=$this->orderNo();$number=$goods[‘num‘]-$goods_number;if($number<0) {$this->echoMsg(0,‘已没有库存‘);
}//mysql判断已购买用户 (自行处理)
//...
$order[‘user_id‘]=$user_id;$order[‘goods_id‘]=$goods[‘id‘];$order[‘number‘]=$goods_number;$order[‘price‘]=$goods[‘money‘];$order[‘status‘]=1;$order[‘sku_id‘]=2;$order[‘order_sn‘]=$orderNo;$order[‘create_time‘]=date(‘Y-m-d H:i:s‘);$this->insert(‘ims_order‘,$order);$sql="update ims_hotmallstore_goods set num=num-".$goods_number." where num>0 and id=".$goods[‘id‘];$res=$this->exec($sql);//echo $sql;die;
if(!empty($res)) {echo "库存扣减成功,库存剩下:$number".PHP_EOL;return false;
}else{$redis=self::Redis();$redis->lpush(‘num‘,$goods_number);//扣库存失败,把库存加回
$redis->SREM(‘user_list_‘.$goods_id,$user_id);//已购买用户集合移除
$this->echoMsg(0,‘库存扣减失败‘);
}
}//保存日志
public function echoMsg($status,$msg,$exit = true) {if($exit == true) {die($msg);
}else{echo $msg;
}
}
}if(!isset($_GET[‘i‘])) {exit(‘缺失参数i‘);
}//调用--将商品库存循环到lpush的num里
if($_GET[‘i‘]==1) {$model = newTest;$model->doPageSaveNum();
}//调用--高并发抢购下单
if($_GET[‘i‘]==2) {$model = newTest;$model->doPageGoodsStore();
}if($_GET[‘i‘]==3) {$model = newTest;for ($i=1; $i<=100; $i++) {$model->doPageGoodsStore();
}
}//http://127.0.0.1/qianggou/test.php?i=1
// ab -n 2000 -c 500 http://127.0.0.1/qianggou/test.php?i=2
// (-n发出2000个请求,-c模拟500并发,请求数要大于或等于并发数。相当2000人同时访问,后面是测试url )