这里我们主要利用 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 锁解决高并发问题的更多相关文章

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

    这里我们主要利用Redis的setnx的命令来处理高并发. setnx 有两个参数.第一个参数表示键.第二个参数表示值.如果当前键不存在,那么会插入当前键,将第二个参数做为值.返回 1.如果当前键存在 ...

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

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

  3. 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存

    原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...

  4. 利用redis实现分布式事务锁,解决高并发环境下库存扣减

    利用redis实现分布式事务锁,解决高并发环境下库存扣减   问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据 ...

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

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

  6. Redis+Lua解决高并发场景抢购秒杀问题

    之前写了一篇PHP+Redis链表解决高并发下商品超卖问题,今天介绍一些如何使用PHP+Redis+Lua解决高并发下商品超卖问题. 为何要使用Lua脚本解决商品超卖的问题呢? Redis在2.6版本 ...

  7. php解决高并发问题

    我们通常衡量一个Web系统的吞吐率的指标是QPS(Query Per Second,每秒处理请求数),解决每秒数万次的高并发场景,这个指标非常关键.举个例子,我们假设处理一个业务请求平均响应时间为10 ...

  8. 转发:php解决高并发

    php解决高并发(转发:https://www.cnblogs.com/walblog/articles/8476579.html) 我们通常衡量一个Web系统的吞吐率的指标是QPS(Query Pe ...

  9. asp.net解决高并发的方案.

    asp.net解决高并发的方案. Posted on 2012-11-27 22:31 75077027 阅读(3964) 评论(1) 编辑 收藏 最近几天一直在读代震军的博客,他是 Discuz!N ...

随机推荐

  1. [CF959F]Mahmoud and Ehab and yet another xor task题解

    搞n个线性基,然后每次在上一次的基础上插入读入的数,前缀和线性基,或者说珂持久化线性基. 然后一个num数组记录当时线性基里有多少数 然后每次前缀操作一下就珂以了 代码 #include <cs ...

  2. form submission

    https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms This module provides a series of articles ...

  3. MySQL工作中遇到的问题记录

    1:log_slave_updates: 从库1搭建级联从库2,从库1需要开启log_slave_updates,修改/etc/my.cnf,增加一行log_slave_updates=1,重启数据库 ...

  4. java Json 技术记录

    1.Json-lib json-lib最开始的也是应用最广泛的json解析工具,json-lib 不好的地方确实是依赖于很多第三方包,包括commons-beanutils.jar,commons-c ...

  5. MySQL 服务器性能剖析

    这是<高性能 MySQL(第三版)>第三章的读书笔记. 关于服务,常见的问题有: 如何确认服务器是否发挥了最大性能 找出执行慢的语句,为何执行慢 为何在用户端发生间歇性的停顿.卡死 通过性 ...

  6. HTML5移动应用——小心代码注入风险

    近日在加州举行的移动安全技术大会上,Syracuse大学的研究者的研究报告显示HTML5移动应用可能会给企业带来新的安全风险.开发者的错误可能导致HTML5应用自动执行攻击者通过Wifi蓝牙或短信发送 ...

  7. cts-verifier测试流程

    测试目的: cts的补充测试,可以理解为没法自动化的cts测试,这个是人工测试. 测试前提: 1.发货user版本 2.selinux:Enable 5.外网环境 设备需求: 2个待测设备:1个手机或 ...

  8. 解决Sql Server服务远程过程调用失败

    方法一:修复Sql Server: 修复过程中若遇到:重新启动计算机失败, 1.按下组合键[Win]+[R],调出运行窗口 2.输入“regedit”,在注册表左侧目录栏中找到如下位置:“HKEY_L ...

  9. 爬虫(十一)—— 请求库(三)pypeteer请求库

    曾经使用模拟浏览器操作(selenium + webdriver)来写爬虫,但是稍微有点反爬的网站都会对selenium和webdriver进行识别,网站只需要在前端js添加一下判断脚本,很容易就可以 ...

  10. Python入门习题10.河内塔(汉诺塔)问题

    例10 共n个圆盘,a,b,c三根柱子 #汉诺塔问题.py def Hanoi(n): #定义n阶汉诺塔问题移动次数函数 if n == 1: return 1 else: return 2*Hano ...