精华内容
下载资源
问答
  • 原标题:如何利用Redis解决高并发问题,看完就知道Redis是有多好用了图书推荐这里我们主要利用Redis的setnx的命令来处理高并发。setnx 有两个参数。第一个参数表示键。第二个参数表示值。如果当前键不存在,那么会...

    原标题:如何利用Redis锁解决高并发问题,看完就知道Redis是有多好用了

    图书推荐

    这里我们主要利用Redis的setnx的命令来处理高并发。

    setnx 有两个参数。第一个参数表示键。第二个参数表示值。如果当前键不存在,那么会插入当前键,将第二个参数做为值。返回 1。如果当前键存在,那么会返回0。

    创建库存表

    CREATETABLE`storage`(

    `id`int( 11) unsignedNOTNULLAUTO_INCREMENT,

    `number`int( 11) DEFAULTNULL,

    PRIMARY KEY( `id`)

    ) ENGINE= InnoDBAUTO_INCREMENT= 1DEFAULTCHARSET=latin1

    设置初始库存为10

    创建订单表

    CREATETABLE`order`(

    `id`int( 11) unsignedNOTNULLAUTO_INCREMENT,

    `number`int( 11) DEFAULTNULL,

    PRIMARY KEY( `id`)

    ) ENGINE= InnoDBAUTO_INCREMENT= 1DEFAULTCHARSET=latin1

    测试不用锁的时候

    $pdo = newPDO( '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|

    + ----+--------+

    1row inset ( 0.00sec)

    在来看订单表

    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 inset (0.00 sec)

    发现存在几个订单都是操作的同一个库存数据,这样就可能引起超卖的情况。

    修改代码加入redis锁进行数据控制

    /**

    * Created by PhpStorm.

    * User: daisc

    * Date: 2018/7/23

    * Time: 14:45

    */

    classLock

    {

    privatestatic$_instance ;

    private$_redis;

    privatefunction__construct()

    {

    $this->_redis = newRedis();

    $this->_redis ->connect('127.0.0.1');

    }

    publicstaticfunctiongetInstance()

    {

    if(self::$_instance instanceof self)

    {

    returnself::$_instance;

    }

    returnself::$_instance = newself();

    }

    /**

    * @function加锁

    * @param$key 锁名称

    * @param$expTime 过期时间

    */

    publicfunctionset($key,$expTime)

    {

    //初步加锁

    $isLock = $this->_redis->setnx($key,time()+$expTime);

    if($isLock)

    {

    returntrue;

    }

    else

    {

    //加锁失败的情况下。判断锁是否已经存在,如果锁存在切已经过期,那么删除锁。进行重新加锁

    $val = $this->_redis->get($key);

    if($val&&$val

    {

    $this->del($key);

    }

    return$this->_redis->setnx($key,time()+$expTime);

    }

    }

    /**

    * @param$key 解锁

    */

    publicfunctiondel($key)

    {

    $this->_redis->del($key);

    }

    }

    $pdo = newPDO('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 inset (0.00 sec)

    发现订单表没有操作同一个库存数据的情况。所以利用redis锁是可以有效的处理高并发的。

    这里在加锁的时候其实是可以不需要判断过期时间的,这里我们为了避免造成死锁,所以加一个过期时间的判断。当过期的时候主动删除该锁。返回搜狐,查看更多

    责任编辑:

    展开全文
  • 网上大部分的用redis解决高并发场景下的锁机制 基本都是利用Redis的setnx的命令来处理高并发 下面我们介绍的是利用redis的 incr命令处理高并发 代码如下 <?php $redis = new Redis(); $redis->connect...

    网上大部分的用redis解决高并发场景下的锁机制

    基本都是利用Redis的setnx的命令来处理高并发

     

    下面我们介绍的是利用redis的 incr命令处理高并发

    代码如下

    <?php
    $redis = new Redis();
    $redis->connect("127.0.0.1", 6379);
    
    if($redis->incr("lock")==1){
    	$redis->EXPIRE("lock",30);  //设置超时时间 防止意外导致死锁 这里是30秒
    //这里写获取到锁以后的代码
    
    $redis->del("lock");  //  执行完成以后删除
    }
    
    ?>
    

    setnx有些时候会导致锁不住的情况 incr目前没有遇到过失效的

    展开全文
  • redis锁处理高并发问题十分常见,下面这篇文章主要给大家介绍了关于如何使用Redis解决高并发问题的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
  • 利用Redis解决并发问题

    千次阅读 2018-10-11 20:54:18
    那如果要使用redis来进行高并发问题的解决的话,应注意以下几点: 1、首先我们要先知道,我们在存储时,应使用redis的setnx方法,不应该使用set方法,因为setnx拥有原子操作命令(正确点说法应该是使用setnx,根据...

    用redis处理高并发是个很常见的方式,因为redis的访问效率很高(直接访问内存),一般我们会用来处理网站一瞬间的并发量。

    那如果要使用redis来进行高并发问题的解决的话,应注意以下几点:

    1、首先我们要先知道,我们在存储时,应使用redis的setnx方法,不应该使用set方法,因为setnx拥有原子操作命令(正确点说法应该是使用setnx,根据其属性可以保证共享资源的原子性操作),当资源锁存在不能设置值,则返回0,而当锁不存在,则设置锁,返回1; 但如果使用set方法,则会出现在高并发情况下,进程同时获取锁状态为null,同时设置,锁之间相互覆盖,但是俩进程仍在并发执行业务代码的情况。

    2、为了防止死锁,我们不应直接使用jedis.setnx(lock, 1) 来进行简单的加锁,这样会导致当进程执行出现问题,锁未释放,则其他进程永远处于阻塞状态,出现死锁。 为了避免死锁,我们在加锁时带上时间戳,setnx(lock, 时间戳+超时时间),当发现锁超时了,便可以对锁进行重置,避免死锁。

    接下来,实际操作!

    设置锁:

    //其中currentTimeMullis为当前时间、valideTime为超时时间,key为资源

    //对该资源进行锁获取,如果存在锁则会返回false,不存在则设置值并返回true

    boolean lock = redisService.setnx(key, currentTimeMullis+valideTime);

    //如果不存在并设置了值,则可以直接返回,因为已经获取资源锁成功

    //否则,则代表存在这个锁,则进行锁是否超时的判断。获取该资源的锁时间,用于判断是否超时了

    String keyTime = redisService.get(key);

    if((Long.valueOf(currentTimeMullis)-Long.valueOf(keyTime))>valideTime){

    //该判断代表该资源锁已经超时,那么便进行资源锁的重置,也就是进行资源锁的重新设置(删除并重新设置)

    //重新设置成功后也返回,因为获取锁成功,可以进行操作啦。

    }

    //如果以上操作都没有成功,则返回失败,代表获取锁失败,不可以进行操作。

    释放锁:

    当对资源处理结束后,则调用释放方法释放锁资源

    (经提醒,我发现我这里少了个判断逻辑…)

    //在删除前,应该先对该资源锁进行获取,判断值与此时释放锁的线程所携带的值是否相等,也就是我们上面创建时用的currentTimeMullis+valideTime。

    String keyLockTime = redisService.get(key);

    if(keyLockTime!=null&&keyLockTime.equals(currentTimeMullis+valideTime)){

    //此时锁还由当前线程保持则释放锁

    redisService.del(key);

    }else{

    //此时说明该资源锁被其他线程重置或释放,已不再拥有锁的释放权

    //结束

    }

    展开全文
  • 利用redis缓存解决高并发下后端重复请求措施

     最近在进行压力测试的时候发现在高并发下,有些接口很可能因为重复请求导致对数据库操作出来的数据不是你想要的那个样子。比如,用户签到,你只想让用户一天签到一次,为了防止签到多次,你对于每次强求,都去查询数据库今天是不是已经签到了,如果签了,就不让继续签到,如果没签到,插入签到数据,更新积分数据什么的。但是数据库操作是有时间的,在高并发下这种方式明显是不能限制重复请求提交的,有可能一个用户一天签到好几次,只要这个提交时间在很短的范围内就行(亲测确实是这样的)。

         于是就引出了今天要讨论的问题,如何处理重复提交的问题。
        首先看看准确的出现重复请求问题的原因(容老夫ctrl+v一段文字):

         在业务开发中,我们常会面对防止重复请求的问题。当服务端对于请求的响应涉及数据的修改,或状态的变更时,可能会造成极大的危害。重复请求的后果在交易系统、售后维权,以及支付系统中尤其严重。

    前台操作的抖动,快速操作,网络通信或者后端响应慢,都会增加后端重复处理的概率。

     前台操作去抖动和防快速操作的措施,我们首先会想到在前端做一层控制。当前端触发操作时,或弹出确认界面,或disable入口并倒计时等等,此处不细表。

     但前端的限制仅能解决少部分问题,且不够彻底,后端自有的防重复处理措施必不可少,义不容辞。   嗯,啰嗦的原因交代完毕,下面来讲讲具体的solution:   我们说是基于redis缓存的处理重复请求的方式,重复请求就是在很短的时间内发送多次请求,这个时间是相当短的,以至于你进行数据库查询来验证都没法取阻挡。这样的话,我们就可以使用一个缓存的计数器来阻止这个问题的发生。在接口的开始,定义一个缓存计数器(该缓存的时间可以是几秒,几十秒或者一两分钟,能完成短时间内多个请求的这个短时间的时间就行),同一个会员的每个进来一个请求就将这个计数器+1(当然就是用会员的id+一些特定的字符串做key),对于大于1的请求不予受理。这样在这个缓存进行的时间段内就能唯一确保只有一个。嗯,具体的实现方式就是这样。(亲测有效)   下面推荐几种处理方式(基本上还是redis缓存机制最好,当然我也是主要从这里借鉴的):
       http://mogu.io/prevent-duplicate-requests-4 
    展开全文
  • 这里我们主要利用Redis的setnx的命令来处理高并发。 setnx有两个参数。第一个参数表示键。第二个参数表示值。如果当前键不存在,那么会插入当前键,将第二个参数做为值。返回1。如果当前键存在,那么会返回0。 ...
  • 这里我们主要利用 Redis 的 setnx 的命令来处理高并发。 setnx有两个参数。第一个参数表示键。第二个参数表示值。如果当前键不存在,那么会插入当前键,将第二个参数做为值。返回1。如果当前键存在,那么会返回0...
  • 感谢作者:旧梦发癫出处:人类身份验证 - SegmentFault这里我们主要利用Redis的setnx的命令来处理高并发。setnx 有两个参数。第一个参数表示键。第二个参数表示值。如果当前键不存在,那么会插入当前键,将第二个...
  • 实现方案较为简单,分为两步走: 1、把数据临时写入redis,减轻前台同时并发写入数据库的压力 2、写一个死循环的PHP,可以判断下每秒钟运行一次,然后把redis里的内容给写入到数据库。 为什么这样解决可以呢?因...
  • 1,Redis ...利用INCR命令簇(INCR, DECR, INCRBY)来把字符串当作原子计数器使用 使用APPEND命令在字符串后添加内容 列表(List) Redis列表是简单的字符串列表,按照插入顺序排序 你可以添...
  • redis之所以能解决高并发的原因是它可以直接访问内存,而以往我们用的是数据库(硬盘),提高了访问效率,解决了数据库服务器压力。 为什么redis的地位越来越高,我们为何不选择memcache,这是因为memcache只能存储字符...
  • 平时多积累点高并发啊锁啊缓存啊这些知识点 面试的时候可以和面试官侃侃而谈 面试官喜欢听高并发相关的 当然你能结合实际业务场景来分析 面试肯定加分 传统单点应用的线程安全问题,因为只涉及到单个应用中...
  • SETNX命令简介 SETNX key value 将key的值设为value,并且仅当key不存在。... 此处放置需要要高并发的代码 */ //代码执行成功则释放锁 redisTemplate.delete( lockKey ); }    
  • 利用redis + lua解决抢红包高并发的问题

    万次阅读 多人点赞 2014-02-20 20:08:26
    redis的抢红包方案,虽然在极端情况下(即redis挂掉)会丢失一秒的数据,但是却是一个扩展性很强,足以应付高并发的抢红包方案。 公众号 欢迎关注公众号:横云断岭的专栏,专注分享Java,Spring Boot,Arthas...
  • 本篇文章主要介绍了利用redis + lua解决抢红包高并发的问题 ,详细的讲诉了需求分析和方案,有兴趣的可以了解一下。
  • 利用乐观锁及redis解决秒杀高并发基本逻辑 //初始化redis $redis = new Redis(); // 设置键值,起到监视作用 执行事务之前,判断被修改,回滚 $redis->watch('sales'); // 获取销量 $sales = $redis->...
  • 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问题描述:某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 方案一 利用数据库锁...
  • 利用redis实现分布式事务锁,解决高并发环境下库存扣减 问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据库锁机制,对记录进行...
  • 本文讲述了Redis高并发问题的解决办法。分享给大家供大家参考,具体如下: redis为什么会有高并发问题 redis的出身决定  redis是一种单线程机制的nosql数据库,基于key-value,数据可持久化落盘。由于单线程所以...
  • redis高并发处理方式其实redis是不会存在并发问题的,因为他是单进程的,再多的命令都是一个接一个地执行的。我们使用的时候,可能会出现并发问题,比如获得和设定这一对。Redis的为什么 有高并发问题?Redis的的...
  • 利用redis性能和事务特性来解决线上优惠券被超库存抢购的问题,下面我给出我临时解决这个问题的第一版的伪代码,去掉了一些细节: /** * 抢优惠券(秒杀) * @param int $couponId 商品ID * @param

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 237
精华内容 94
关键字:

利用redis解决高并发

redis 订阅