redis 解决库存并发问题实现数量控制


Posted in Redis onApril 08, 2022

redis是单进程,阻塞式,在同一时刻只能处理一个请求,后来的请求需要排队等待。

优点:因为是单进程,所以无需处理并发问题,降低 系统复杂度

缺点:不适合缓存大尺寸对象(超过100kb)

原因: 由于Redis只使用单核,而Memcached可以使用多核,所以平均每一个核上Redis在存储小数据时比Memcached性能更高。

而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis也在存储大数据的性能上进行了优化,但是比起Memcached,还是稍有逊色。

memcache是多进程,非阻塞式,如果仅仅作为缓存来用,可以用memcache更合适

redis 解决库存并发问题实现数量控制

一、命令

exists 查看该键key是否已存在redis中, 例如 exists mycounter

set 设置初始化一个key值 例如 set mycounter 99

get 获取一个key值 例如 getmycounter

incr 自增1 例如 incrmycounter //输出结果为100

incrby 指定增长值 例如 incrbymycounter 2 //输出结果为102

指定减少值 例如 incrbymycounter -2 //输出结果为100

setnx 当值不存在时,设置该值成功 例如 setnxmycounter 99 //输出结果为0,代表设置失败,已存在redis中

setnx key1 12 //输出结果为1,代表设置成功,之前未存在redis中

expire 设置一个键的生命周期 例如 expire mycounter 30 //设置为30秒有效期

ttl 获取key失效时间 例如 ttlmycounter //输出为 13,代表还有13秒 ,如果返回为-1,代表永不过期,永远存在redis缓存中,除非内存不足

//如果返回为-2,代表已失效,redis无该键值,可以用exists验证,返回0,代表不存

二、常见场景

商品抢购,数量没控制住,库存超限,成本不足(例如:库存1000,却被用户成功抢购2000,库存不足)

抽奖限量,没控制住,钱多花了

抢红包

三、流程图与代码

方案1 流程图:

redis 解决库存并发问题实现数量控制

方案2流程图:

redis 解决库存并发问题实现数量控制

//方案1代码,测试坏境TP5
public function redisCountV1(){
    Log::record("测试版本1并发开始", Log::INFO);
    $redis = new Redis();
    //总库存数量
    $amountLimit = 100;
    //redis存储库存键名
    $keyName = "mycounter_v6";
    //假设每次消耗库存数为1
    $incrAmount = 1;
    //判断redis中是否 存在该值,如果不存在,则用set设置(问题是如果出现并发,两个或多个用户同时访问,会导致库存重新设置)
    if(!$redis->exists($keyName)){
        $redis->set($keyName, 95);
    }
    //从redis中取出当前库存数
    $currAmount = $redis->get($keyName);
    //如果当前库存数+增长的库存数>总库存,直接返回
    if($currAmount + $incrAmount > $amountLimit) {
        file_put_contents("/Users/han/Documents/www/cs/testv1.log", "bad luck \n", FILE_APPEND);
        Log::record("bad luck", Log::INFO);
        return false;
    }
    //缓存库存数量增加
    $redis->incrby($keyName, $incrAmount);
    file_put_contents("/Users/han/Documents/www/cs/testv1.log", "good luck \n", FILE_APPEND);
    Log::record("good luck", Log::INFO);
}

//测试方式:ab  -c 100 -n 200 http://www.fenleduo.com:8080/V7/Test/redisCountV1
//方案2代码,测试坏境TP5
public function redisCountV2(){
    Log::record("测试版本2并发开始", Log::INFO);
    $redis = new Redis();
    //总库存数量
    $amountLimit = 100;
    //redis存储库存键名
    $keyName = "mycounter_v12";
    //假设每次消耗库存数为1
    $incrAmount = 1;
    //判断redis中是否 存在该值,如果不存在,则用setnx设置(注:如果出现并发,两个或多个用户同时访问,不会导致库存重新设置)
    if(!$redis->exists($keyName)){
        //setnx 如果不存在该值,则设置,如果存在则不会设置
        $redis->setnx($keyName, 95);
    }
    //从redis中取出当前库存数
    $currAmount = $redis->get($keyName);
    //如果当前库存数+增长的库存数>总库存,直接返回
    if($redis->incrby($keyName, $incrAmount) > $amountLimit) {
        file_put_contents("/Users/han/Documents/www/cs/testv2.log", "bad luck \n",FILE_APPEND);
        Log::record("bad luck", Log::INFO);
        return false;
    }
    file_put_contents("/Users/han/Documents/www/cs/testv2.log", "good luck \n",FILE_APPEND);
    Log::record("good luck", Log::INFO);
}
//测试方式:ab  -c 100 -n 200 http://www.fenleduo.com:8080/V7/Test/redisCountV2

到此这篇关于redis 解决库存并发问题实现数量控制的文章就介绍到这了,更多相关redis  库存并发内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Redis 相关文章推荐
redis cluster支持pipeline的实现思路
Jun 23 Redis
redis不能访问本机真实ip地址的解决方案
Jul 07 Redis
嵌入式Redis服务器在Spring Boot测试中的使用教程
Jul 21 Redis
Redis如何实现分布式锁
Aug 23 Redis
Redis集群新增、删除节点以及动态增加内存的方法
Sep 04 Redis
Redis命令处理过程源码解析
Feb 12 Redis
面试分析分布式架构Redis热点key大Value解决方案
Mar 13 Redis
解决 Redis 秒杀超卖场景的高并发
Apr 12 Redis
详解Redis的三种常用的缓存读写策略步骤
May 06 Redis
Redis特殊数据类型bitmap位图
Jun 01 Redis
redis lua限流算法实现示例
Jul 15 Redis
python中使用redis用法详解
Dec 24 Redis
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
 Redis 串行生成顺序编码的方法实现
浅谈Redis 中的过期删除策略和内存淘汰机制
一文搞懂Redis中String数据类型
Apr 03 #Redis
使用Redis做预定库存缓存功能
sentinel支持的redis高可用集群配置详解
You might like
第4章 数据处理-php字符串的处理-郑阿奇(续)
2011/07/04 PHP
php Xdebug的安装与使用详解
2013/06/20 PHP
解析php php_openssl.dll的作用
2013/07/01 PHP
php自动获取关键字的方法
2015/01/06 PHP
php实现网站文件批量压缩下载功能
2015/10/28 PHP
php实现socket推送技术的示例
2017/12/20 PHP
Laravel项目中timeAgo字段语言转换的改善方法示例
2019/09/16 PHP
锋利的jQuery 要点归纳(三) jQuery中的事件和动画(下:动画篇)
2010/03/24 Javascript
6个DIV 135或246间隔一秒轮番显示效果
2010/07/24 Javascript
jQuery.prototype.init选择器构造函数源码思路分析
2013/02/05 Javascript
简介JavaScript中用于处理正切的Math.tan()方法
2015/06/15 Javascript
jquery+json实现动态商品内容展示的方法
2016/01/14 Javascript
AngularJS模仿Form表单提交的实现代码
2016/12/08 Javascript
TypeScript学习之强制类型的转换
2016/12/27 Javascript
Vue.js 中取得后台原生HTML字符串 原样显示问题的解决方法
2018/06/10 Javascript
Vue引入sass并配置全局变量的方法
2018/06/27 Javascript
jQuery实现提交表单时不提交隐藏div中input的方法
2019/10/08 jQuery
基于Vue中的父子传值问题解决
2020/07/27 Javascript
简单的通用表达式求10乘阶示例
2014/03/03 Python
python实现批量修改文件名代码
2017/09/10 Python
Python文本处理之按行处理大文件的方法
2018/04/09 Python
Pycharm2017版本设置启动时默认自动打开项目的方法
2018/10/29 Python
python 实现矩阵上下/左右翻转,转置的示例
2019/01/23 Python
python实现五子棋游戏
2019/06/18 Python
Python sep参数使用方法详解
2020/02/12 Python
HTML5 拖放功能实现代码
2016/07/14 HTML / CSS
澳大利亚相机之家:Camera House
2017/11/30 全球购物
轻松制作精彩视频:Animoto
2018/09/19 全球购物
英国领先的新鲜松露和最好的松露产品供应商:TruffleHunter
2019/08/26 全球购物
中国领先的汽车保养服务平台:途虎养车
2019/10/18 全球购物
吸烟检讨书2000字
2014/02/13 职场文书
汽车维修专业自荐书
2014/05/26 职场文书
2015年房产销售工作总结范文
2015/05/22 职场文书
Python实战之用tkinter库做一个鼠标模拟点击器
2021/04/27 Python
python人工智能human learn绘图可创建机器学习模型
2021/11/23 Python
基于Python实现将列表数据生成折线图
2022/03/23 Python