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锁解决高并发问题相关推荐

  1. 利用Redis锁解决高并发问题

    利用Redis锁解决高并发问题 参考文章: (1)利用Redis锁解决高并发问题 (2)https://www.cnblogs.com/yszr/p/11698696.html 备忘一下.

  2. java redis队列_redis队列实现高并发怎么用?Java如何使用redis队列解决高并发?

    小伙伴们大家好,不知道你们有没有在Java开发中遇到redis队列高并发,这个问题让你很头疼,今天小编就来讲解一下在Java中遇到redis队列高并发了,到底该怎么办. 高并发的业务场景: 我们做商品 ...

  3. PHP利用Mysql锁解决高并发

    前面写过利用文件锁来处理高并发的问题的,现在我们说另外一个处理方式,利用Mysql的锁来解决高并发的问题 先看没有利用事务的时候并发的后果 创建库存管理表 CREATE TABLE `storage` ...

  4. 91免费视频Redis+Lua解决高并发场景在线秒杀问题

    为何要使用Lua脚本解决商品超卖的问题呢? Redis在2.6版本后原生支持Lua脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行. 将复杂的或者多步的redis操作,写为一个脚本,一次 ...

  5. mysql乐观锁 秒杀_使用数据库乐观锁解决高并发秒杀问题,以及如何模拟高并发的场景,CyclicBarrier和CountDownLatch类的用法...

    数据库:mysql 数据库的乐观锁:一般通过数据表加version来实现,相对于悲观锁的话,更能省数据库性能,废话不多说,直接看代码 第一步: 建立数据库表: CREATE TABLE `skill_ ...

  6. 数据库并发抢红包_Redis悲观锁解决高并发抢红包的问题

    悲观锁是一种利用数据库内部机制提供的锁的方法,也就是对更新的数据加锁,这样在并发期间一旦有一个事务持有了数据库记录的锁,其他的线程将不能再对数据进行更新了,这就是悲观锁的实现方式. 首先在 RedPa ...

  7. mysql 高并发写入锁表_使用mysql中的锁解决高并发问题

    阿里云产品通用代金券,最高可领1888分享一波阿里云红包. 阿里云的购买入口 为什么要加锁 多核计算机的出现,计算机实现真正并行计算,可以在同一时刻,执行多个任务.在多线程编程中,因为线程执行顺序不可 ...

  8. Zookeeper锁实现分布式锁解决高并发高可用秒杀系统

    抢购前数据 库存表 订单表 zookeeper配置类 /*** @Author yqq* @Date 2022/05/30 23:24* @Version 1.0*/ @Configuration p ...

  9. redis解决高并发问题,如商品秒杀

    redis真的是一个很好的技术,它可以很好的在一定程度上解决网站一瞬间的并发量,例如商品抢购秒杀等活动... redis之所以能解决高并发的原因是它可以直接访问内存,而以往我们用的是数据库(硬盘),提 ...

最新文章

  1. appium-java长按学习
  2. 【竞赛相关】南大化院博士刘子腾:跨专业如何做数据竞赛浅谈
  3. 更新鸿蒙系统运行评价,全球首批!升级使用鸿蒙OS真实反馈评价出炉:差评/好评都很真实...
  4. 如何查看数据文件或者Log文件是否增长过?
  5. linux apache24 使用,科学网—linux_centos第24_2次课Apache的安装 - 郭会强的博文
  6. 16位的数字高字节和低字节_掩盖8位数字的较低和较高半字节| 8085微处理器
  7. 2782: [HNOI2006]最短母串
  8. MS speech SDK5.1朗读控件
  9. 20211010 PHP笔记
  10. Rust 与 Objective-C 互操作
  11. HDU2545 树上战争【树+并查集】
  12. 关于GPS坐标系和地图定位偏差
  13. c++实现单例模式完整源代码
  14. Netty权威指南学习笔记
  15. hibernate lazy属性参数说明
  16. SD-Host SD_CLK模块
  17. tadf发光原理 热活化延迟荧光(TADF)原理是什么?
  18. 蓝桥杯题目 2682: 蓝桥杯2022年第十三届省赛真题-GCD
  19. 双系统重装ubuntu18.04
  20. Elasticsearch:rollup - 索引管理

热门文章

  1. 适合平面设计的无盘服务器配置,适合平面设计的电脑配置
  2. golang爬虫框架colly简单介绍
  3. 什么内容的短视频可以吸引粉丝?分享五种类型短视频,供你选择
  4. 计算机软件类ui工资多少,合肥UI设计工资一般多少
  5. 快速入手springboot
  6. 北邮2019网络安全学业网络研究学院机试复试回忆版
  7. 大学生角度_LeapMotion结合Unity开发体感游戏_03
  8. nc 探测端口_使用 nc 命令检查远程端口是否打开
  9. 破解中国电商未来新趋势 看唯品会如何顺势而为?
  10. ltd弹出 rust steam_《Rust》在Steam上已被退款33万份 损失438万美元