• 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');
    

      

  • 相关阅读:
    svn_linux + apache 实现网页访问svn
    SVN_2008R2 搭建流程与规范
    mysql 简称
    论运维之故障排查思路与方法
    mac pro 基本使用
    防火墙之netfailt、iptables详解
    翻转单词顺序列(剑指offer)
    中缀变为后缀
    左旋转字符串(剑指offer)
    和为S的两个数字(剑指offer)
  • 原文地址:https://www.cnblogs.com/yxhblogs/p/6800460.html
Copyright © 2020-2023  润新知