Redis锁解决高并发问题
Redis锁解决高并发问题
redis真的是一个很好的技术,它可以很好的在一定程度上解决网站一瞬间的并发量,例如商品抢购秒杀等活动。
redis之所以能解决高并发的原因是它可以直接访问内存,而以往我们用的是数据库(硬盘),提高了访问效率,解决了数据库服务器压力。
为什么redis的地位越来越高,我们为何不选择memcache,这是因为memcache只能存储字符串,而redis存储类型很丰富(例如有字符串、LIST、SET等),memcache每个值最大只能存储1M,存储资源非常有限,十分消耗内存资源。
而redis可以存储1G,最重要的是memcache它不如redis安全,当服务器发生故障或者意外关机等情况时,redsi会把内存中的数据备份到硬盘中,而memcache所存储的东西全部丢失;这也说明了memcache不适合做数据库来用,可以用来做缓存。
这里我们主要利用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锁进行数据控制
<?phpclass 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);}}/*** @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锁是可以有效的处理高并发的。
这里在加锁的时候其实是可以不需要判断过期时间的,这里我们为了避免造成死锁,所以加一个过期时间的判断。当过期的时候主动删除该锁。
Redis锁解决高并发问题相关推荐
- 利用Redis锁解决高并发问题
利用Redis锁解决高并发问题 参考文章: (1)利用Redis锁解决高并发问题 (2)https://www.cnblogs.com/yszr/p/11698696.html 备忘一下.
- java redis队列_redis队列实现高并发怎么用?Java如何使用redis队列解决高并发?
小伙伴们大家好,不知道你们有没有在Java开发中遇到redis队列高并发,这个问题让你很头疼,今天小编就来讲解一下在Java中遇到redis队列高并发了,到底该怎么办. 高并发的业务场景: 我们做商品 ...
- PHP利用Mysql锁解决高并发
前面写过利用文件锁来处理高并发的问题的,现在我们说另外一个处理方式,利用Mysql的锁来解决高并发的问题 先看没有利用事务的时候并发的后果 创建库存管理表 CREATE TABLE `storage` ...
- 91免费视频Redis+Lua解决高并发场景在线秒杀问题
为何要使用Lua脚本解决商品超卖的问题呢? Redis在2.6版本后原生支持Lua脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行. 将复杂的或者多步的redis操作,写为一个脚本,一次 ...
- mysql乐观锁 秒杀_使用数据库乐观锁解决高并发秒杀问题,以及如何模拟高并发的场景,CyclicBarrier和CountDownLatch类的用法...
数据库:mysql 数据库的乐观锁:一般通过数据表加version来实现,相对于悲观锁的话,更能省数据库性能,废话不多说,直接看代码 第一步: 建立数据库表: CREATE TABLE `skill_ ...
- 数据库并发抢红包_Redis悲观锁解决高并发抢红包的问题
悲观锁是一种利用数据库内部机制提供的锁的方法,也就是对更新的数据加锁,这样在并发期间一旦有一个事务持有了数据库记录的锁,其他的线程将不能再对数据进行更新了,这就是悲观锁的实现方式. 首先在 RedPa ...
- mysql 高并发写入锁表_使用mysql中的锁解决高并发问题
阿里云产品通用代金券,最高可领1888分享一波阿里云红包. 阿里云的购买入口 为什么要加锁 多核计算机的出现,计算机实现真正并行计算,可以在同一时刻,执行多个任务.在多线程编程中,因为线程执行顺序不可 ...
- Zookeeper锁实现分布式锁解决高并发高可用秒杀系统
抢购前数据 库存表 订单表 zookeeper配置类 /*** @Author yqq* @Date 2022/05/30 23:24* @Version 1.0*/ @Configuration p ...
- redis解决高并发问题,如商品秒杀
redis真的是一个很好的技术,它可以很好的在一定程度上解决网站一瞬间的并发量,例如商品抢购秒杀等活动... redis之所以能解决高并发的原因是它可以直接访问内存,而以往我们用的是数据库(硬盘),提 ...
最新文章
- appium-java长按学习
- 【竞赛相关】南大化院博士刘子腾:跨专业如何做数据竞赛浅谈
- 更新鸿蒙系统运行评价,全球首批!升级使用鸿蒙OS真实反馈评价出炉:差评/好评都很真实...
- 如何查看数据文件或者Log文件是否增长过?
- linux apache24 使用,科学网—linux_centos第24_2次课Apache的安装 - 郭会强的博文
- 16位的数字高字节和低字节_掩盖8位数字的较低和较高半字节| 8085微处理器
- 2782: [HNOI2006]最短母串
- MS speech SDK5.1朗读控件
- 20211010 PHP笔记
- Rust 与 Objective-C 互操作
- HDU2545 树上战争【树+并查集】
- 关于GPS坐标系和地图定位偏差
- c++实现单例模式完整源代码
- Netty权威指南学习笔记
- hibernate lazy属性参数说明
- SD-Host SD_CLK模块
- tadf发光原理 热活化延迟荧光(TADF)原理是什么?
- 蓝桥杯题目 2682: 蓝桥杯2022年第十三届省赛真题-GCD
- 双系统重装ubuntu18.04
- Elasticsearch:rollup - 索引管理
热门文章
- 适合平面设计的无盘服务器配置,适合平面设计的电脑配置
- golang爬虫框架colly简单介绍
- 什么内容的短视频可以吸引粉丝?分享五种类型短视频,供你选择
- 计算机软件类ui工资多少,合肥UI设计工资一般多少
- 快速入手springboot
- 北邮2019网络安全学业网络研究学院机试复试回忆版
- 大学生角度_LeapMotion结合Unity开发体感游戏_03
- nc 探测端口_使用 nc 命令检查远程端口是否打开
- 破解中国电商未来新趋势 看唯品会如何顺势而为?
- ltd弹出 rust steam_《Rust》在Steam上已被退款33万份 损失438万美元