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' ); |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战