利用 Redis 锁解决高并发问题
这里我们主要利用 Redis 的 setnx 的命令来处理高并发。
setnx 有两个参数。第一个参数表示键。第二个参数表示值。如果当前键不存在,那么会插入当前键,将第二个参数做为值。返回 1。如果当前键存在,那么会返回 0 。
创建库存表
CREATE TABLE `storage` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`number` int(11) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1
设置初始库存为10
创建订单表
CREATE TABLE `order` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`number` int(11) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1
测试不用锁的时候
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'root');$sql="select `number` from storage where id=1 limit 1";$res = $pdo->query($sql)->fetch();$number = $res['number'];if($number>0){$sql ="insert into `order` VALUES (null,$number)";$order_id = $pdo->query($sql);if($order_id){$sql="update storage set `number`=`number`-1 WHERE id=1";$pdo->query($sql);}}
ab 测试模拟并发,发现库存是正确的。
mysql> select * from storage;+----+--------+| id | number |+----+--------+| 1 | 0 |+----+--------+1 row in set (0.00 sec)
在来看订单表
mysql> select * from `order`;+----+--------+| id | number |+----+--------+| 1 | 10 || 2 | 10 || 3 | 9 || 4 | 7 || 5 | 6 || 6 | 5 || 7 | 5 || 8 | 5 || 9 | 4 || 10 | 1 |+----+--------+10 rows in set (0.00 sec)
发现存在几个订单都是操作的同一个库存数据,这样就可能引起超卖的情况。
修改代码加入 redis 锁进行数据控制
<?php/*** Created by PhpStorm.* User: daisc* Date: 2018/7/23* Time: 14:45*/class Lock{private static $_instance ;private $_redis;private function __construct(){$this->_redis = new Redis();$this->_redis ->connect('127.0.0.1');}public static function getInstance(){if(self::$_instance instanceof self){return self::$_instance;}return self::$_instance = new self();}/*** @function 加锁* @param $key 锁名称* @param $expTime 过期时间*/public function set($key,$expTime){//初步加锁$isLock = $this->_redis->setnx($key,time()+$expTime);if($isLock){return true;}else{//加锁失败的情况下。判断锁是否已经存在,如果锁存在切已经过期,那么删除锁。进行重新加锁$val = $this->_redis->get($key);if($val&&$val<time()){$this->del($key);return $this->_redis->setnx($key,time()+$expTime);}return false;}}/*** @param $key 解锁*/public function del($key){$this->_redis->del($key);}}$pdo = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'root');$lockObj = Lock::getInstance();//判断是能加锁成功if($lock = $lockObj->set('storage',10)){$sql="select `number` from storage where id=1 limit 1";$res = $pdo->query($sql)->fetch();$number = $res['number'];if($number>0){$sql ="insert into `order` VALUES (null,$number)";$order_id = $pdo->query($sql);if($order_id){$sql="update storage set `number`=`number`-1 WHERE id=1";$pdo->query($sql);}}//解锁$lockObj->del('storage');}else{//加锁不成功执行其他操作。}
再次进行 ab 测试,查看测试结果
mysql> select * from `order`;+----+--------+| id | number |+----+--------+| 1 | 10 || 2 | 9 || 3 | 8 || 4 | 7 || 5 | 6 || 6 | 5 || 7 | 4 || 8 | 3 || 9 | 2 || 10 | 1 |+----+--------+10 rows in set (0.00 sec)
发现订单表没有操作同一个库存数据的情况。所以利用 redis 锁是可以有效的处理高并发的。
这里在加锁的时候其实是可以不需要判断过期时间的,这里我们为了避免造成死锁,所以加一个过期时间的判断。当过期的时候主动删除该锁。
出处:http://u6.gg/s2mCt
利用 Redis 锁解决高并发问题的更多相关文章
- 利用Redis锁解决高并发问题
这里我们主要利用Redis的setnx的命令来处理高并发. setnx 有两个参数.第一个参数表示键.第二个参数表示值.如果当前键不存在,那么会插入当前键,将第二个参数做为值.返回 1.如果当前键存在 ...
- PHP利用Mysql锁解决高并发
前面写过利用文件锁来处理高并发的问题的,现在我们说另外一个处理方式,利用Mysql的锁来解决高并发的问题 先看没有利用事务的时候并发的后果 创建库存管理表 CREATE TABLE `storage` ...
- 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存
原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...
- 利用redis实现分布式事务锁,解决高并发环境下库存扣减
利用redis实现分布式事务锁,解决高并发环境下库存扣减 问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据 ...
- 使用数据库乐观锁解决高并发秒杀问题,以及如何模拟高并发的场景,CyclicBarrier和CountDownLatch类的用法
数据库:mysql 数据库的乐观锁:一般通过数据表加version来实现,相对于悲观锁的话,更能省数据库性能,废话不多说,直接看代码 第一步: 建立数据库表: CREATE TABLE `skill_ ...
- Redis+Lua解决高并发场景抢购秒杀问题
之前写了一篇PHP+Redis链表解决高并发下商品超卖问题,今天介绍一些如何使用PHP+Redis+Lua解决高并发下商品超卖问题. 为何要使用Lua脚本解决商品超卖的问题呢? Redis在2.6版本 ...
- php解决高并发问题
我们通常衡量一个Web系统的吞吐率的指标是QPS(Query Per Second,每秒处理请求数),解决每秒数万次的高并发场景,这个指标非常关键.举个例子,我们假设处理一个业务请求平均响应时间为10 ...
- 转发:php解决高并发
php解决高并发(转发:https://www.cnblogs.com/walblog/articles/8476579.html) 我们通常衡量一个Web系统的吞吐率的指标是QPS(Query Pe ...
- asp.net解决高并发的方案.
asp.net解决高并发的方案. Posted on 2012-11-27 22:31 75077027 阅读(3964) 评论(1) 编辑 收藏 最近几天一直在读代震军的博客,他是 Discuz!N ...
随机推荐
- Docker Toolbox 学习教程【转载】
最近在研究虚拟化,容器和大数据,所以从Docker入手,下面介绍一下在Windows下怎么玩转Docker.Docker本身在Windows下有两个软件,一个就是Docker,另一个是Docker T ...
- 20180826(01)-Java数据结构
Java 数据结构 Java工具包提供了强大的数据结构.在Java中的数据结构主要包括以下几种接口和类: 枚举 (Enumeration) 位集合(BitSet) 向量 (Vector) 栈 (Sta ...
- Swap——hdu 2819
Swap Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- jsqlparser
摘要:SQL语法解释器jsqlparser 是用java开发的解析器,可以生成java类层次结构. 主页地址:http://jsqlparser.sourceforge.net 可以完美解析表的增删查 ...
- Dpr ppi 适配 等概念 弹性属性的讲解
Dpr: Dpr的全称(Device pixel ratio)像素设备比例:就是说每个设备像素上占有的css位像素的个数 苹果手机常见的设备像素比:1.0安卓 iPhone2.0 3.0 如果是1. ...
- CDN:BootCDN
ylbtech-CDN:BootCDN BootCDN稳定.快速.免费的前端开源项目 CDN 加速服务共收录了 3351 个前端开源项目 1. 推荐返回顶部 1. bootstrap Bootstra ...
- Proxifier全局代理
0x00前言 成功搭建使用shadowshocks实现代理访问google,然而只能浏览器代理方式使用,不能其他程序使用代理,不利于白帽子匿名安全检测,下面将介绍利用Proxifier实现全局代理 ...
- MySQL5.7的搭建以及SSL证书
Centos7 安装MySQL 5.7 (通用二进制包) 1.1 下载软件包 https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.17-l ...
- hive 排序
1.全局排序(order by) Order by:全局排序,只有一个reducer ASC(ascend):升序(默认) DESC(descend):降序 2.每个MR内部排序(sort by) s ...
- [Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分)
[Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分) 题面 给出一个无向图,以及q条有向路径.问是否存在一种给边定向的方案,使得 ...