利用 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 ...
随机推荐
- [CF959F]Mahmoud and Ehab and yet another xor task题解
搞n个线性基,然后每次在上一次的基础上插入读入的数,前缀和线性基,或者说珂持久化线性基. 然后一个num数组记录当时线性基里有多少数 然后每次前缀操作一下就珂以了 代码 #include <cs ...
- form submission
https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms This module provides a series of articles ...
- MySQL工作中遇到的问题记录
1:log_slave_updates: 从库1搭建级联从库2,从库1需要开启log_slave_updates,修改/etc/my.cnf,增加一行log_slave_updates=1,重启数据库 ...
- java Json 技术记录
1.Json-lib json-lib最开始的也是应用最广泛的json解析工具,json-lib 不好的地方确实是依赖于很多第三方包,包括commons-beanutils.jar,commons-c ...
- MySQL 服务器性能剖析
这是<高性能 MySQL(第三版)>第三章的读书笔记. 关于服务,常见的问题有: 如何确认服务器是否发挥了最大性能 找出执行慢的语句,为何执行慢 为何在用户端发生间歇性的停顿.卡死 通过性 ...
- HTML5移动应用——小心代码注入风险
近日在加州举行的移动安全技术大会上,Syracuse大学的研究者的研究报告显示HTML5移动应用可能会给企业带来新的安全风险.开发者的错误可能导致HTML5应用自动执行攻击者通过Wifi蓝牙或短信发送 ...
- cts-verifier测试流程
测试目的: cts的补充测试,可以理解为没法自动化的cts测试,这个是人工测试. 测试前提: 1.发货user版本 2.selinux:Enable 5.外网环境 设备需求: 2个待测设备:1个手机或 ...
- 解决Sql Server服务远程过程调用失败
方法一:修复Sql Server: 修复过程中若遇到:重新启动计算机失败, 1.按下组合键[Win]+[R],调出运行窗口 2.输入“regedit”,在注册表左侧目录栏中找到如下位置:“HKEY_L ...
- 爬虫(十一)—— 请求库(三)pypeteer请求库
曾经使用模拟浏览器操作(selenium + webdriver)来写爬虫,但是稍微有点反爬的网站都会对selenium和webdriver进行识别,网站只需要在前端js添加一下判断脚本,很容易就可以 ...
- Python入门习题10.河内塔(汉诺塔)问题
例10 共n个圆盘,a,b,c三根柱子 #汉诺塔问题.py def Hanoi(n): #定义n阶汉诺塔问题移动次数函数 if n == 1: return 1 else: return 2*Hano ...