php+redis实现高并发模拟下单、秒杀、抢购操作

对于高并发下的场景,一般都是采用redis缓存机制来处理。

当然也不是只有redis可以处理、还有利用mysql事务操作锁住操作的行、文件锁。

不过这些方式都没有redis缓存高效、可靠。

模拟的过程:

首先将商品库存,存储到redis当中。

使用redis队列、来实现相应的操作。

1
2
3
4
5
6
7
8
9
10
11
12
<?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');
?>

下单过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?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('库存减少失败');
    }  
?>

模拟的数据表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*
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');

  

posted @   Yxh_blogs  阅读(1589)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示