-
2021-01-19 07:08:34
用redis实现计数器
社交产品业务里有很多统计计数的功能,比如:
用户: 总点赞数,关注数,粉丝数
帖子: 点赞数,评论数,热度
消息: 已读,未读,红点消息数
话题: 阅读数,帖子数,收藏数
统计计数的特点
实时性要求高
写的频率很高
写的性能对MySQL是一个挑战
可以采用redis来优化高频率写入的性能要求。
redis优化方案一
对于每一个实体的计数,设计一个hash结构的counter:
//用户
counter:user:{userID}
-> praiseCnt: 100 //点赞数
-> hostCnt: 200 //热度
-> followCnt: 332 //关注数
-> fansCnt: 123 //粉丝数
//帖子
counter:topic:{topicID}
-> praiseCnt: 100 //点赞数
-> commentCnt: 322 //评论数
//话题
counter:subject:{subjectID}
-> favoCnt: 312 //收藏数
-> viewCnt: 321 //阅读数
-> searchCnt: 212 //搜索进入次数
-> topicCnt: 312 //话题中帖子数
类似这种计数器,随着产品功能的增加,也会越来越多,比如回复数,踩数,转发数什么的。
redis相关的命令
//获取指定userID的所有计数器
HGETALL counter:user:{userID}
//获取指定userID的指定计数器
HMGET counter:user:{userID} praiseCnt hostCnt
//指定userID点赞数+1
HINCRBY counter:user:{userID} praiseCnt
缺点:这样设计,如果要批量查询多个用户的数据,就比较麻烦,例如一次要查指定20个userID的计数器?只能循环执行 HGETALL counter:user:{userID}。
优点:以实体聚合数据,方便数据管理
redis优化方案二
方案二是用来解决方案一的缺点的,依然是采用hash,结构设计是这样的:
counter:user:praiseCnt
-> userID_1001: 100
-> userID_1002: 200
-> userID_1003: 332
-> userID_1004: 123
.......
-> userID_9999: 213
counter:user:hostCnt
-> userID_1001: 10
-> userID_1002: 290
-> userID_1003: 322
-> userID_1004: 143
.......
-> userID_9999: 213
counter:user:followCnt
-> userID_1001: 21
-> userID_1002: 10
-> userID_1003: 32
-> userID_1004: 203
.......
-> userID_9999: 130
获取多个指定userID的点赞数的命令变成这样了
HMGET counter:user:praiseCnt userID_1001 userID_1002
上面命令可以批量获取多个用户的点赞数,时间复杂度为O(n),n为指定userID的数量。
优点:解决了批量操作的问题
缺点:当要获取多个计数器,比如同时需要praiseCnt,hostCnt时,要读多次,不过要比第一种方案读的次数要少。一个hash里的字段将会非常宠大,HMGET也许会有性能瓶颈。
用redis管道(Pipelining)来优化方案一
对于第一种方案的缺点,可以通过redis管道来优化,一次性发送多个命令给redis执行:
$userIDArray = array(1001, 1002, 1003, 1009);
$pipe = $redis->multi(Redis::PIPELINE);
foreach ($userIDArray as $userID) {
$pipe->hGetAll('counter:user:' . $userID);
}
$replies = $pipe->exec();
print_r($replies);
还有一种方式是在redis上执行lua脚本,前提是你必须要学会写lua。
更多相关内容 -
redis实现计数器-防止刷单方法介绍
2021-01-21 15:11:24比如:一个接口请求,限制每秒请求总数为200次,超过200次就等待,等下一秒,再次请求,这里用到一个redis作为一个计数器的模式来实现。 调用redis的方法: INCR key 将 key 中储存的数字值增一。 如果 key 不存在... -
Redis实现计数器功能(接口最大访问次数检查)
2020-10-20 17:56:06Redis实现计数器功能(接口最大访问次数检查) 1.前言 备注:不要全部粘贴代码,这个是我练习项目的代码(基于spring-boot),主要看2和3的逻辑 1.还是一个简单的redis使用Demo,包含setIfAbsent(不存在则插入),...Redis实现计数器功能(接口最大访问次数检查)
1.前言
备注:不要全部粘贴代码,这个是我练习项目的代码(基于spring-boot),主要看2和3的逻辑
1.还是一个简单的redis使用Demo,包含setIfAbsent(不存在则插入),setIfPresent(存在则更新),getExpire(获取剩余有效时间)
2.大体业务逻辑如下:检查用户请求系统的最大次数,每日最大请求次数为10.
3.也可以使用定时任务实现时效性配置(定时任务00:00执行,清空所有用户访问次数)2.Redis配置
pom文件redis配置:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
properties文件redis配置:
#redis 配置 spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.jedis.pool.max-active=8 spring.redis.timeout=2000
redis序列化配置:
配置序列化,防止插入redis乱码(默认二进制)import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisUtil { /** * 因为序列化使用的jdkSerializeable ,redis存储数据默认为二进制,简单来说key和value是乱码 * 所以自定义序列化类 */ @Bean public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); // 使用Jackson2JsonRedisSerialize 替换默认序列化 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); // 设置value的序列化规则和 key的序列化规则 redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; } }
3.redis判断访问次数
RedisService代码:
public interface RedisService { /** * 更新时效性数据--String类型 **/ Boolean updateVaildValue(String key, String value); /** * 判断当前用户是否达到访问最大次数 **/ Boolean judgeMaxTimesByUserId(String key, String min, String max); }
RedisServiceImpl代码:
import com.example.demo.util.redisUtil.RedisService.RedisService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.math.BigDecimal; import java.util.concurrent.TimeUnit; @Slf4j @Service public class RedisServiceImpl implements RedisService { @Autowired private StringRedisTemplate stringRedisTemplate; /** * @Author longtao * @Date 2020/10/20 * @Describe 更新失效性数据 保留剩余有效时间 **/ @Override public synchronized Boolean updateVaildValue(String key, String value) { //获取剩余时间 单位秒 Long balanceSeconds = stringRedisTemplate.opsForValue().getOperations().getExpire(key); if (balanceSeconds > 0) { return stringRedisTemplate.opsForValue().setIfPresent(key, value, balanceSeconds, TimeUnit.SECONDS); } return false; } /** * @Author longtao * @Date 2020/10/20 * @Describe 判断 最大访问次数 > userId当前访问次数 **/ @Override public synchronized Boolean judgeMaxTimesByUserId(String key, String min, String max) { //获取key的值,为null时则插入新的 //不为null时,取出数据进行判断:是否达到最大值 String value = stringRedisTemplate.opsForValue().get(key); if(StringUtils.isEmpty(value)){ //这里时间暂用的24小时,也可以计算得到当前时间到24:00点的毫秒时间。 stringRedisTemplate.opsForValue().setIfAbsent(key,min,24,TimeUnit.HOURS); return true; } //最大次数 <= 当前访问次数 if(new BigDecimal(max).compareTo(new BigDecimal(value)) <= 0 ){ return false; } return updateVaildValue(key,new BigDecimal(value).add(new BigDecimal(1)).toString()); } }
4.切面调用检查逻辑
切面注解----CheckVisitTimesAroundAnnotation代码:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface CheckVisitTimesAroundAnnotation { }
切面注解----CheckVisitTimesAroundAspection代码:
//返回异常对象
return new BaseResponse<>(ResultEnum.CHECK_USER_ID_VISIT_TIMES);
这个可以换成日志输出,这里直接粘贴了我的Demo项目代码。import com.alibaba.excel.util.StringUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.example.demo.base.Enum.ResultEnum; import com.example.demo.base.model.baseModel.BaseModel; import com.example.demo.base.model.baseRequest.BaseRequest; import com.example.demo.base.model.baseResponse.BaseResponse; import com.example.demo.util.redisUtil.RedisService.RedisService; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import java.lang.reflect.Method; @Aspect @Component @Slf4j @Order(2) public class CheckVisitTimesAroundAspection { @Autowired private RedisService redisService; /** * 切入点 */ @Pointcut("@annotation(com.example.demo.base.annonation.CheckVisitTimesAroundAnnotation) ") public void entryPoint() { } /** * @return * @Describe 前置切面 */ @Around("entryPoint()") public Object aroundMethod(ProceedingJoinPoint proceedingJoinPoint) { log.info("------检查userId访问次数限制------start"); Object[] args = proceedingJoinPoint.getArgs(); //打印入口方法以及入参 try { for (Object arg : args) { Boolean flag = judgeVisitTimesByUserId(arg); if(!flag){ //返回异常对象 return new BaseResponse<>(ResultEnum.CHECK_USER_ID_VISIT_TIMES); } } } catch (Exception e) { e.printStackTrace(); log.debug("不能打印请求参数"); } //执行请求方法 Object o = null; try { o = proceedingJoinPoint.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } log.info("------检查userId访问次数限制------end"); return o; } //检查userId请求接口限制 public Boolean judgeVisitTimesByUserId(Object object){ BaseModel baseModel = JSONObject.parseObject(JSONObject.toJSONString(object),BaseModel.class); String userId = baseModel.getUserId(); if(!StringUtils.isEmpty(userId)){ return redisService.judgeMaxTimesByUserId(userId,"1","10"); } return true; } }
在controller层方法上增加注解代码:
增加@CheckVisitTimesAroundAnnotation注解@BaseBeforeAnnotation @CheckVisitTimesAroundAnnotation @RequestMapping("selectOne") public BaseResponse selectReaderInfo(@RequestBody ReaderInfoModel model) { ReaderInfoModel bookInfoModel = readerInfoService.selectOne(model.getId()); return new BaseResponse(ResultEnum.SUCCESS,bookInfoModel); }
4.执行结果
redis中:userId 的值:
postman收到的返回值:
最后:本次写的比较仓促,我要接我老婆了。有不足的地方望大家指正和包涵! -
使用redis 作为计数器
2022-07-01 14:47:03使用redis 作为计数器使用redis 作为计数器
我们公司的业务 需要生成订单号大致格式是
kd01 0001 20220701 拼接的订单号 中间的0001是用作计数的
用来判断这是今天第几个单
工具类:
package com.plz.manager.util; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import java.time.LocalDate; import java.util.Calendar; import java.util.Date; import java.util.concurrent.TimeUnit; /** * @Author HappyLiu * @Description //封装redis计数器方法 * @Date 9:15 2022/7/1 **/ public class KdOrderIdUtil { public KdOrderIdUtil() { } /** * 这个方法 是返回一个 000120220701的字符串 * 我们公司的业务 需要生成订单号大致格式是 * kd01 0001 20220701 拼接的订单号 中间的0001是用作计数的 * 用来判断这是今天第几个单 */ public static String getOrderId(RedisTemplate redisTemplate) { String key = "plz_num"; String code = ""; // 判断key是否存在 如果存在将value递增1 if (redisTemplate.hasKey(key)) { int value = redisTemplate.boundValueOps(key).increment(1).intValue(); code = String.format("%04d", value);//变成0001,如果想变成001---“%03d” } else { // 根据当前时间 距离凌晨还剩多少秒 用来给Key设置过期时间 Integer second = getRemainSecondsOneDay(new Date()); redisTemplate.opsForValue().set(key, "1", second, TimeUnit.SECONDS); code = String.format("%04d", 1); } LocalDate today = LocalDate.now(); String YMD = today.toString().replaceAll("-", ""); return code + YMD; } /** * 这个方法是用来获取当前时间距离凌晨00:00 还有多少毫秒(秒) * 用来给redis设置过期时间 */ public static Integer getRemainSecondsOneDay(Date currentDate) { Calendar midnight = Calendar.getInstance(); midnight.setTime(currentDate); midnight.add(midnight.DAY_OF_MONTH, 1);//将日加1 midnight.set(midnight.HOUR_OF_DAY, 0);//控制时 midnight.set(midnight.MINUTE, 0);//控制分 midnight.set(midnight.SECOND, 0);//控制秒 midnight.set(midnight.MILLISECOND, 0);//毫秒 //通过以上操作就得到了一个currentDate明天的0时0分0秒的Calendar对象,然后相减即可得到到明天0时0点0分0秒的时间差 // 返回以秒为单位的秒数 Integer second = (int) (midnight.getTime().getTime() - currentDate.getTime()) / 1000; // 返回以毫秒为单位的毫秒数 // Long millisecond = (midnight.getTimeInMillis() - currentDate.getTime()); return second; } }
controller:
先把RedisTemplate 注册到容器中
然后使用工具类调用 传入即可
@Autowired private RedisTemplate redisTemplate @RequestMapping("/test") public R getOrderid() { String orderId1 = KdOrderIdUtil.getOrderId(redisTemplate); String orderId2 = KdOrderIdUtil.getOrderId(redisTemplate); String orderId3 = KdOrderIdUtil.getOrderId(redisTemplate); String kd = "kd"; String kdOrderId1 = kd+"01"+ orderId1; String kdOrderId2 = kd+"01"+ orderId2; String kdOrderId3 = kd+"01"+ orderId3; List<String> list = new ArrayList<>(); list.add(kdOrderId1); list.add(kdOrderId2); list.add(kdOrderId3); return R.ok().put("list",list); }
测试结果
{ "msg": "success", "code": 0, "list": [ "kd01000120220701", "kd01000220220701", "kd01000320220701" ] }
-
redis用作计数器
2022-03-03 16:04:09使用redis用作计数器,可以记录当前的key的次数,可以对key进行增加,也可以用作文章的点赞数,阅读量,先保存到redis中,如果有需要就可以保存到数据库当中,也可以用作某个用户的的访问次数(可以使用用户的ip作为...- 当遇到需求,在规定时间,用户的访问量不能超过规定次数的时候就可以用redis中的计数器来实现了
- 又可以使用这个技术用来做限流(使用用户的ip作为key,用户访问一次,就加1,如果超过次数就返回false)
- 可以处理业务上面的的一些访问次数之类的,例如:文章的点赞数,阅读量,允许有一点的延迟效果,先保存到redis中,然后在同步到数据库当中
- 首先我们先初始化一下RedisTemplate,这个是操作redis的第三方库,我们先要对他初始化一下(重新序列化)
- 先把StringRedisTemplate注入进来,这里有人会用RedisTemplate可能会报错,可能是序列化的问题,私下百度一下就行了
@Autowired private StringRedisTemplate stringRedisTemplate;
@Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(connectionFactory); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); // 这个地方不可使用 json 序列化,如果使用的是ObjectRecord传输对象时,可能会有问题,会出现一个 java.lang.IllegalArgumentException: Value must not be null! 错误 redisTemplate.setHashValueSerializer(RedisSerializer.string()); return redisTemplate; } }
- 然后我们就可以用@Autowired进行注入到spring容器中使用了,这里我将方法都放在一个类中,用作与测试的
/** * 利用redis做计数器 * 可以处理业务上面的的一些访问次数之类的 * 例如:文章的点赞数,阅读量,允许有一点的延迟效果,先保存到redis中,然后在同步到数据库当中 */ @RequestMapping("hello") public void count() { /** * 判断是否到达次数 */ Boolean aBoolean = invokeExceededTimes("time_key2",1,3); if (aBoolean) { LOGGER.info("可以访问"); }else { LOGGER.info("请求次数达标了"); } } /** * 判断同一个key在规定时间内访问次数是否到达了最高值 * @param key 键 * @param days 时间 * @param count 一定时间内的访问次数 * @return */ public Boolean invokeExceededTimes(String key, int days, int count) { LOGGER.info("key值:{}",key); // 判断在redis中是否有key值 Boolean redisKey = stringRedisTemplate.hasKey(key); if (redisKey) { // 获取key所对应的value Integer hasKey =Integer.parseInt((String)stringRedisTemplate.opsForValue().get(key)); if (hasKey >= count) { return false; } // 对value进行加1操作 stringRedisTemplate.opsForValue().increment(key,1); return true; }else { // 如果没有key值,对他进行添加到redis中 stringRedisTemplate.opsForValue().set(key,"1",days,TimeUnit.DAYS); } return true; }
- 这里面有用到这两个方法,关注一下
// 对value进行加1操作 stringRedisTemplate.opsForValue().increment(key,1);
// 判断在redis中是否有key值 Boolean redisKey = stringRedisTemplate.hasKey(key);
- 最后我测试的是同一个key只能访问三次,当然根据业务需求来就行了,我这里只是一个测试
- 就到这里了,后面会分享更多的关于redis的操作
-
Redis实现高并发计数器
2020-09-09 07:13:38主要为大家详细介绍了Redis实现高并发计数器,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 -
java redis实现访问计数器
2020-08-25 10:47:41redis工具类 @SuppressWarnings(value = { "unchecked", "rawtypes" }) @Component public class RedisCache { @Autowired public RedisTemplate redisTemplate; /** * 缓存基本的对象,Integer、String、实体... -
基于redis实现最简单的计数器限流算法
2022-07-03 16:17:40基于redis实现最简单的计数器限流算法 -
利用Redis实现高并发计数器
2021-05-09 14:35:57使用Redis的Incr自增命令可以轻松实现以上需求。以一个接口一天限制调用次数为例: 接口例子 1、是否拒绝服务 /** * 是否拒绝服务 * @return */ private boolean denialOfService(String userId){ ... -
Java利用Redis实现高并发计数器
2021-03-23 15:27:24使用Redis的Incr自增命令可以轻松实现以上需求。以一个接口一天限制调用次数为例: /** * 是否拒绝服务 * @return */ private boolean denialOfService(String userId){ long count=JedisUtil.setIncr(DateUtil.... -
用redis实现计数器
2019-04-08 08:57:17用redis实现计数器 社交产品业务里有很多统计计数的功能,比如: 用户: 总点赞数,关注数,粉丝数 帖子: 点赞数,评论数,热度 消息: 已读,未读,红点消息数 话题: 阅读数,帖子数,收藏数 统计计数的特点... -
多线程中redis实现计数器总结
2018-03-15 11:10:00三、计数器实现 背景:控制1分钟内的请求拉取照片次数 1、原代码实现: 1 String key = "gateway_ext_fetchdata_" + model.getExtCode(); 2 try { 3 String accessCount = flowControl.get(key)... -
基于Redis实现高并发计数器(lua脚本版)
2021-05-11 01:21:42文章目录1、业务需求背景2、代码实现2.1、RedisConfig.java2.2、RedisController.java2.3、redis_incr.lua3、测试效果4、总结 1、业务需求背景 一个手机号一天限制发送5条短信、一个接口一分钟限制多少请求、一个... -
Redis Lua脚本简介、以及Redis实现计数器
2020-04-20 00:04:58Redis在2.6推出了脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行。 使用Lua脚本的好处 减少网络开销:通过在脚本中定义多条命令(甚至业务逻辑)可以减少了网络I/O开销。从这一点上看其比管道功能更强大。... -
Redis实现计数器---接口防刷
2017-12-03 22:07:081、Redis是单线程,我接触的很多人对这个概念有误解,我目录理解所谓单线程是指其在执行一个命令时是原子的不会被其他的命令所打断。 2、处女版分图解: 3、重生版图解: 4、大家可以结合... -
redis作为计数器的使用
2020-12-16 10:02:48redis计数器,记录某活动使用量 刚刚入行的小白,什么都不太懂,最近某活动要求奖品领取量上限为20万,就想到用redis来实现,代码如下: 代码片段 String redisKey= "Activity"; RedisUtil.setString(keyString, "0... -
基于springboot+redis的分布式计数器限流接口(附详细代码注释和项目地址)
2022-03-06 13:39:22项目结构整体预览1.AccessLimiter 限流接口2.AccessLimiter 接口实现类3.Limit 标签接口,实现注解方式4.LimitAspect 切面实现5.GenerateRedisKey 生成保存策略的key值6.ConfigInfo类 获取设备id7.RedisConfig redis... -
PHP基于redis计数器类定义与用法示例
2021-03-24 08:14:23本文实例讲述了PHP基于redis计数器类定义与用法。分享给大家供大家参考,具体...这里使用其incr(自增),get(获取),delete(清除)方法来实现计数器类。1.Redis计数器类代码及演示实例RedisCounter.class.php/*** P... -
Redis 多方式实现计数器功能
2021-02-12 18:48:10在这篇文章里,我会使用 Redis 的三种数据类型,来分别实现计数器的功能。请跟随我一起来看看吧。 使用字符串键下面代码演示了如何利用 Redis 中的字符串键来实现计数器功能。其中,incr() 方法用于累加计数,get_... -
redis counter demo – redis并发计数器
2021-02-28 07:58:40一、说明利用redis操作的原子性,实现java 多线程并发的情况下实现计数器。我本机测试多个线程操作之后,结果会出现一定的延迟,但是最终数字是ok的应该是redis内部做了一个类似于队列的功能。需要注意的是,得使用... -
Redis原子计数器incr,防止并发请求
2017-10-17 15:14:19一些对高并发请求有限制的系统或者功能里,比如说秒杀活动,或者一些网站返回的当前用户过多,请稍后...而在各种限流中,除了系统自身设计的带锁机制的计数器外,利用Redis实现显然是一种既高效安全又便捷方便的方式。 -
redis 计数器
2020-09-04 16:21:43在监控应用程序的同时,持续地收集信息是一件...为了收集指标数据并进行监视和分析,我们将构建一个能够持续创建并维护计数器的工具,这个工具创建的每个计数器都有自己的名字(名字里带有网站点击量、销量或者数据库查询字 -
redis--计数器和限流器
2021-09-26 10:25:351 原理和实现 限速器的典型用法是限制公开 API 的请求次数,以下是一个限速器实现示例,它将 API 的最大请求数限制在每个 IP 地址每秒钟十个之内: FUNCTION LIMIT_API_CALL(ip) ts = CURRENT_UNIX_TIME() ... -
redis 分布式计数器
2019-10-02 10:52:29使用redis的string类型可以实现分布式计数器 ****************************************************** 使用示例:使用计数器统计对某一路径的访问次数 实现方式:创建计数器,拦截器对指定的路径拦截获取相关... -
Redis实现计数器---接口防刷---升级版(Redis+Lua)
2018-03-18 19:54:39Cash Loan(一):Redis实现计数器---接口防刷 中介绍了项目中应用redis来做计数器的实现过程,最近自己看了些关于Redis实现分布式锁的代码后,发现在Redis分布式锁中出现一个问题在这版计数器中同样会出现,于是... -
PHP使用redis计数器
2019-05-13 15:25:00实例化Redis; 使用redis自带的函数incr(为键 key 储存的数字值加上一) 假如用户1首先进来 $num 打印出来为1; 如果用户1连续请求两次 $num 打印出来为2; 阻止用户再次提交 最怕一生碌碌无为,还安慰自己平凡...