# redis计数器与数量控制 **Repository Path**: Yenn-2017_admin/redis-incrby ## Basic Information - **Project Name**: redis计数器与数量控制 - **Description**: redis计数器与数量控制 视频学习练习 - **Primary Language**: Java - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2023-02-27 - **Last Updated**: 2023-06-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # redis计数器与数量控制 #### 介绍 redis计数器与数量控制 https://www.imooc.com/learn/1067 视频学习练习 简介:介绍redis的设计目的,应用场景,redis的工作模式与优缺点;介绍redis常用的5种数据类型;介绍redis计数器相关命令;介绍如何用redis计数器实现并发场景下的精准数量控制。 ## 第1章 课程介绍 课程内容介绍 ## 1-1 redis数量控制器-课程介绍 #### 课程介绍 认识Redis的本质:设计目标,应用场景 理解Redis的工作模式 认识Redis计数器 如何用Redis计数器实现并发场景下的数量控制 #### Redis是什么 缓存 数据库 消息代理 #### Redis与Memcache对比 Memcache是内存对象缓存系统,设计目标为通过缓解数据库的压力来加快web应用的响应速度 Redis应用场景更丰富, Memcache仅适合作为缓存使用 #### Redis的工作模式 ◆单进程单进程单进程(重要的事情说三遍!!!) ◆阻塞式 Redis在同一时刻只能处理一个请求,后来的请求需要排队等待! #### Redis优缺点 优点:无需处理并发问题,降低系统复杂度 缺点:不适合缓存大尺寸对象(超过100KB) (为什么? ) #### Redis常用数据类型 STRING字符串。整数型字符串 HASH哈希。PHP关联数组, Python字典 LIST列表。Python元组 SET集合。集合中的元素唯一 ZSET有序集合。元素有分值,用于排序 Redis的数据类型如此丰富,如果仅仅当作缓存来用,确实是“杀鸡焉用牛刀”。Memcache更合适。 #### Redis计数器 #### 应用场景 频率控制:接口防刷,密码尝试次数限制。 数量统计:请求量统计。 数量控制:商品抢购,奖励额度控制。 ### 第2章 redis数量控制 介绍redis的设计目的,应用场景,redis的工作模式与优缺点;介绍redis常用的5种数据类型;介绍redis计数器相关命令;介绍如何用redis计数器实现并发场景下的精准数量控制。 ## 2-1 redis数量控制器-命令演示 (08:13)] ```shell 127.0.0.1:6379> exists mycounter (integer) 0 127.0.0.1:6379> set mycounter 99 OK 127.0.0.1:6379> get mycounter "99" 127.0.0.1:6379> incr mycounter (integer) 100 127.0.0.1:6379> get mycounter "100" 127.0.0.1:6379> incrby mycounter 2 (integer) 102 127.0.0.1:6379> get mycounter "102" 127.0.0.1:6379> incrby mycounter -2 (integer) 100 127.0.0.1:6379> get mycounter "100" 127.0.0.1:6379> setnx mycounter 99 (integer) 0 127.0.0.1:6379> setnx mycounter1 99 (integer) 1 127.0.0.1:6379> get mycounter1 "99" 127.0.0.1:6379> get mycounter "100" 127.0.0.1:6379> expire mycounter 30 (integer) 1 127.0.0.1:6379> ttl mycounter (integer) 19 127.0.0.1:6379> ttl mycounter (integer) -1 127.0.0.1:6379> exists mycounter (integer) 1 127.0.0.1:6379> ttl mycounter (integer) -1 ``` ## 2-2 redis数量控制器-V1、V2版 (09:15)] ### 应用场景 商品抢购。没控制住?库存不够了,成本失控 抽奖限量。没控制住?钱多花了 抢红包。 ### 数量控制器v1 ![image-20230228094726045](./images/数量控制器V1.png) - 并发场景:客户端A、B同时访问数量控制器 - 问题1 : A先执行incrby ,然后B执行set ,数据不-致 - 问题2 : 假定限量100,A、B同时读到当前数量为99 , A、B执行完incrby后,总量为101 , 超限了 ### 数量控制器v2 ![image-20230228095036815](./images/数量控制器V2.png) - 改进1 : 初始化使用setnx取代set - 改进2 : 执行incrby后判断是否超限 ## 2-3 redis数量控制器-源代码编写 (07:59)] ```java /** * 数量控制器v1 * * @return */ @GetMapping("/count/v1") @ApiOperation(value = "数量控制器v1") public ResponseEntity> countV1() { String key = PREFIX + "v1"; int amountLimit = 100; int incrAmount = 1; if (Objects.isNull(intOperations.get(key))) { intOperations.set(key, 95); } Integer currAmount = intOperations.get(key); if (currAmount + incrAmount > amountLimit) { log.info(" Bad Luck :{},{},currAmount + incrAmount > amountLimit={}", key, amountLimit,currAmount + incrAmount > amountLimit); } else { intOperations.set(key, currAmount + incrAmount); log.info(" Good Luck :{},{},currAmount + incrAmount > amountLimit={}", key, amountLimit,currAmount + incrAmount > amountLimit); } return ResponseUtils.res(currAmount.toString()); } /** * 数量控制器v2 * * @return */ @GetMapping("/count/v2") @ApiOperation(value = "数量控制器v2") public ResponseEntity> countV2() { String key = PREFIX + "v2"; int amountLimit = 100; Long incrAmount = 1L; int startValue = 95; if (!intRedisTemplate.hasKey(key)) { intRedisTemplate.opsForValue().setIfAbsent(key, startValue); } Integer currAmount = intRedisTemplate.opsForValue().get(key); Long increment = intRedisTemplate.opsForValue().increment(key, incrAmount); if (increment.intValue() > amountLimit) { log.info(" Bad Luck :{},{}", key, amountLimit); } else { log.info(" Good Luck :{},{}", key, amountLimit); } return ResponseUtils.res(currAmount.toString()); } ``` ## 2-4 redis数量控制器-并发测试 (05:43)] ### 一、安装 centos:yum install httpd-tools -y ubuntu:apt install httpd-tools -y windows: 下载 https://www.apachehaus.com/cgi-bin/download.plx ![image-20230301091847124](./images/安装HTTPD.png) 修改配置文件的监听端口从80更改为其他比如8090 ![image-20230301092221079](./images/修改配置文件.png) 用ab命令来进行压力测试 **ab -n100 -c50 http://127.0.0.1:3000/** 常用参数: ***-n: 请求个数\*** ***-c:并发量(模拟请求的客户端数量)\*** ***-t: 多少秒内进行并发\*** ### 命令 ```shell ab -n 200 -c 100 http://localhost:8080/demo/count/v2 ab -n 200 -c 100 http://localhost:8080/demo/count/v1 ``` ## 第3章 课程总结 课程内容总结 ## 3-1 redis数量控制器-课程总结 (00:58)] Redis的本质 Redis的工作模式 用Redis实现计数器 用Redis计数器实现并发场景下的数量控制