zoukankan      html  css  js  c++  java
  • 使用redis防止抢购商品超卖

    前言:

    • redis不仅仅是单纯的缓存,它还有一些特殊的功能,在一些特殊场景上很好用。
    • 本篇博文用来测试下使用redis来防止抢购商品超卖问题。

    内容:

    • 使用redis的list进行测试

        思路是设置一个redis列表List,假设有十个商品,每次请求先判断List的长度,小于十就能抢到商品,将用户信息存放到List中。代码如下

     //进行抢购
        protected function way_list(){
            $num = $this->redis->lLen();
            if($this->redis->lLen()>=self::AMOUNTLIMIT){
                $this->writeLog("抢购失败".$num);
                return;
            }else{
                $this->redis->rPush($num);
                $this->writeLog("抢购成功".$num);
            }
        }

    结果:失败!

    可以很明显数量不对顺序也不对。

    分析了下原因,在代码执行时,多用户并发请求时,第一个用户判断List长度符合条件还未进行List写入时,第二个用户也通过了List长度判断。所以就导致执行失败。

    这就没有利用到redis的原子性

    所以进行了改良

    • 使用redis 的incrby。incrby将制定key 的值增加指定的增量,并返回增量后的值。是一个原子性操作。所谓的原子性操作就是执行该方法后要嘛成功要嘛失败。

    思路就是设置一个键值对存放被抢购数量,每次一个用户进来就将该值加一进行判断,如果小于抢购的商品数量则抢购成功,否则失败。代码如下

     protected function way_string(){
            //判断是否有初始化
            if(!$this->redis->exists(self::sold_name)){
                $this->redis->setnx(self::sold_name,0);
            }
            if($this->redis->incrby(self::sold_name,1) > self::AMOUNTLIMIT){
                $this->writeLog('失败');
            }else{
                $this->writeLog('成功');
            }
        }

    结果

    压力测试了几次都没有出现问题

    通过apache自带的ab压力测试,进行五百次连接请求,并发三百次,没有出现超卖行为。

    总结:会出现超卖主要是由于用户在请求的时候,代码在执行是有先后,会导致执行结果不符合预期。而采用redis的原子性就能避免。

  • 相关阅读:
    jekyll简单使用
    三、ansible简要使用
    四、ansible主机组定义
    项目中远程连接404 NOT FOUND问题的原因以及解决办法(这里只涉及我遇到的问题)
    AS3中的位操作
    AS3中is和as操作符的区别
    static 函数和普通函数的区别
    [译] SystemTap
    2017-09-17 python 学习笔记
    xargs 命令使用小记
  • 原文地址:https://www.cnblogs.com/lsrd/p/10241141.html
Copyright © 2011-2022 走看看