php+redis实现高并发模拟下单、秒杀、抢购操作
对于高并发下的场景,一般都是采用redis缓存机制来处理。
当然也不是只有redis可以处理、还有利用mysql事务操作锁住操作的行、文件锁。
不过这些方式都没有redis缓存高效、可靠。
模拟的过程:
首先将商品库存,存储到redis当中。
使用redis队列、来实现相应的操作。
<?php $store = 500;//模拟库存 $redis = new Redis(); $result = $redis->connect('127.0.0.1',6379); $res = $redis->llen('goods_store'); echo $res."<br/>"; $count = $store - $res; for($i=0;$i<$count;$i++){ $redis->lpush('goods_store',1);//入队列一个商品 } echo $redis->llen('goods_store'); ?>
下单过程:
<?php header("Content-Type:text/html;charset=utf-8"); $conn = mysql_connect("192.168.139.136","root","1234"); if(!$conn){ echo "数据库连接失败";exit(); } mysql_select_db("shop",$conn); mysql_query("set names utf8"); //生成唯一订单号 function build_order_no(){ return date("ymd").substr(implode(NULL, array_map('ord',str_split(substr(uniqid(),7,13),1))),0,8); } //记录日志 function insertLog($event,$type=0){ global $conn; $sql = "INSERT INTO `shop_log`(`event`,`type`) VALUES('{$event}',{$type})"; //echo $sql; mysql_query($sql,$conn); } //模拟场景 $price = 10; $user_id = 1; $goods_id = 1; $sku_id = 11; $number = 1; //模拟下单操作 //下单时判断redis队列库存量 $redis = new Redis(); $result = $redis->connect("127.0.0.1",6379); $count = $redis->lpop("goods_store");//下单一次、队列中弹出一个商品 if(!$count){ insertLog("redis中没有库存"); return; } $order_sn=build_order_no(); //生成订单 $sql="INSERT INTO `shop_order`(`order_sn`,`user_id`,`goods_id`,`sku_id`,`price`) VALUES({$order_sn},{$user_id},{$goods_id},{$sku_id},{$price})"; $order_res=mysql_query($sql,$conn); //库存减少 $sql="UPDATE `shop_store` SET `number` = number - {$number} WHERE `sku_id` = {$sku_id}"; $store_res=mysql_query($sql,$conn); if(mysql_affected_rows()){ insertLog('库存减少成功'); }else{ insertLog('库存减少失败'); } ?>
模拟的数据表:
/* Navicat MySQL Data Transfer Source Server : centos(1) Source Server Version : 50552 Source Host : 192.168.139.136:3306 Source Database : shop Target Server Type : MYSQL Target Server Version : 50552 File Encoding : 65001 Date: 2017-05-03 10:08:23 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for shop_goods -- ---------------------------- DROP TABLE IF EXISTS `shop_goods`; CREATE TABLE `shop_goods` ( `goods_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '商品ID', `cat_id` int(11) NOT NULL COMMENT '商品分类ID', `goods_name` varchar(255) NOT NULL COMMENT '商品名称', PRIMARY KEY (`goods_id`) ) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='@商品表'; -- ---------------------------- -- Records of shop_goods -- ---------------------------- INSERT INTO `shop_goods` VALUES ('1', '0', '小米手机'); -- ---------------------------- -- Table structure for shop_log -- ---------------------------- DROP TABLE IF EXISTS `shop_log`; CREATE TABLE `shop_log` ( `id` int(11) NOT NULL AUTO_INCREMENT, `event` varchar(255) NOT NULL, `type` tinyint(4) NOT NULL DEFAULT '0', `addtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=91602 DEFAULT CHARSET=utf8 COMMENT='@日志表'; -- ---------------------------- -- Records of shop_log -- ---------------------------- -- ---------------------------- -- Table structure for shop_order -- ---------------------------- DROP TABLE IF EXISTS `shop_order`; CREATE TABLE `shop_order` ( `id` int(11) NOT NULL AUTO_INCREMENT, `order_sn` char(32) NOT NULL, `user_id` int(11) NOT NULL, `status` int(11) NOT NULL DEFAULT '0', `goods_id` int(11) NOT NULL DEFAULT '0', `sku_id` int(11) NOT NULL DEFAULT '0', `price` float NOT NULL, `addtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2022 DEFAULT CHARSET=utf8 COMMENT='@订单表'; -- ---------------------------- -- Records of shop_order -- ---------------------------- -- ---------------------------- -- Table structure for shop_store -- ---------------------------- DROP TABLE IF EXISTS `shop_store`; CREATE TABLE `shop_store` ( `id` int(11) NOT NULL AUTO_INCREMENT, `goods_id` int(11) NOT NULL, `sku_id` int(10) unsigned NOT NULL DEFAULT '0', `number` int(10) unsigned NOT NULL DEFAULT '0', `freez` int(11) NOT NULL DEFAULT '0' COMMENT '虚拟库存', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='@库存'; -- ---------------------------- -- Records of shop_store -- ---------------------------- INSERT INTO `shop_store` VALUES ('1', '1', '11', '0', '0');