我的编程空间,编程开发者的网络收藏夹
学习永远不晚

利用Redis实现访问次数限流的方法详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

利用Redis实现访问次数限流的方法详解

假设我们要做一个业务需求,这个需求就是限制用户的访问频次。比如1分钟内只能访问20次,10分钟内只能访问200次。因为是用户维度的场景,性能肯定是要首先考虑,那么适合这个场景的非Redis莫属。

最简单的实现,莫过于只是用incr进行计数操作,于是有了下面的代码:


long count = redisTemplate.opsForValue().increment("user:1:60");
if (count > maxLimitCount) {
   throw new LimitException("访问太频繁");
}

count = redisTemplate.opsForValue().increment("user:1:600");
if (count > maxLimitCount) {
   throw new LimitException("访问太频繁");
}

来,我们对上面这段代码解读一下。需求有2个时间维度的限制,所以这边基于用户和时间维度构建了Redis的Key。然后对每个Key进行计数,计数后的结果用于跟限制的值进行判断,如果超出了限制的值就抛出异常。

假设限制的时间场景有10个呢?那上面的代码是不是得写10遍才可以。有人可能会说,这还不简单吗?循环呀,循环确实能够解决这个问题。但是大家有没有去思考,这是用户维度的请求,如果每个请求里面都去操作10次Redis的话,这耗时至少也得10来毫秒吧。所以问题在这,并不是说这个逻辑实现的有问题。

那我们就改成批量的吧,用pipeline来批量执行。

redisTemplate.execute(new RedisCallback<Long>() {
    @Override
    public Long doInRedis(RedisConnection connection) throws DataAccessException {
        connection.openPipeline();
        connection.incr("user:1:60".getBytes());
        connection.incr("user:1:600".getBytes());
        onnection.closePipeline();
        return null;
    }
});

用pipeline也有一个问题,那就是拿不到返回值,也就只能增加,但是没办法判断是否超过了限制的阀值。

所以需要在第一步先查询下,用查到的值进行判断,这样也就是只需要和Redis交互两次就可以了。

上面的代码在单节点下没问题,但是如果在集群下,其实每个Key都可能分配到不同的节点上去,只不过是底层帮你屏蔽掉了细节,并发执行,拿到了所有结果后合并返回的。所以我们需要让所有的Key都路由到一个节点上,本来就是用户维度的,直接使用userId路由即可。

这个时候Redis的HashTag功能就排上用场了,将Key user:1:600改写成user:{1}:600 。

虽然已经优化了,但是还是要发起两次网络请求才能完成这个逻辑,有没有可能再进一步优化下呢?一次请求行不行。

这个时候要放大招了,Lua脚本走起,将所有逻辑都放入Lua脚本中,一次网络交互即可完成。

local current
current = redis.call("incr",KEYS[1])
if current == 1 then
    redis.call("expire",KEYS[1],1)
end

if current > ARGV[1]
  return 1
end

return 0

上面脚本演示了如何对一个Key进行处理,返回1表示限流,返回0表示通过。不过使用lua脚本的时候要注意,某些云服务的Redis会对脚本进行校验,像Redis的Key不能使用变量,必须用KEYS[下标]的方式,所以这里操作多个Key还不能用循环,代码得写多遍,这是一个恶心的点。

总结

到此这篇关于利用Redis实现访问次数限流的文章就介绍到这了,更多相关Redis访问次数限流内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

利用Redis实现访问次数限流的方法详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

使用Redis实现记录访问次数的三种方案

目录0. 前言1. 使用Filter实现2. 使用AOP实现1. 导入依赖2. 写一个切面类,实现统计访问次数。3. 开启AOP5. plus版本3. 使用springMVC拦截器实现1. 配置拦截器2. 定义拦截器3. 控制器类4. 测试
使用Redis实现记录访问次数的三种方案
2024-09-06

Java限流实现的几种方法详解

这篇文章主要介绍了Java限流实现的几种方法,通俗的说,限流就是限制一段时间内,用户访问资源的次数,减轻服务器压力,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2022-12-03

Redis实现IP限流的2种方式举例详解

目录通过reids实现通过Lua+Redis实现注意事项总结 通过reids实现限流的流程图在配置文件配置限流参数blackIP:# ip 连续请求的次数continue-counts: ${counts:3}# ip 判断的时间间隔
Redis实现IP限流的2种方式举例详解
2024-08-13

Springboot使用redis实现接口Api限流的方法

这篇文章主要介绍“Springboot使用redis实现接口Api限流的方法”,在日常操作中,相信很多人在Springboot使用redis实现接口Api限流的方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答
2023-06-20

基于Redis实现分布式应用限流的方法

限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务。前几天在DD的公众号,看了一篇关于使用 瓜娃 实现单应用限流的方案 --》原文,参考《redis in action》 实
2023-05-30

如何利用VB.NET数据库访问方法封装到类实现

这期内容当中小编将会给大家带来有关如何利用VB.NET数据库访问方法封装到类实现,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。我们都知道,线程要执行的方法不能接受任何参数,如果要传入方法特定条件,可以将方
2023-06-17

Golang官方限流器time/rate的使用与实现详解

限流器是后台服务中十分重要的组件,在实际的业务场景中使用居多。time/rate 包基于令牌桶算法实现限流,本文主要为大家介绍了time/rate的使用与实现,需要的可以参考一下
2023-05-18

利用node.js实现反向代理的方法详解

本文主要给大家介绍的是关于利用node.js实现反向代理的相关内容,分享出供大家参考学习,下面话不多说,来一起看看详细的介绍: 跨域问题是前端开发很常见的问题解决方案有很多种jsonp返回Access-Control-Allow-Origi
2022-06-04

Java利用StampedLock实现读写锁的方法详解

在jdk8以后,java提供了一个性能更优越的读写锁并发类StampedLock,该类的设计初衷是作为一个内部工具类,用于辅助开发其它线程安全组件。本文就来和大家一起学习下StampedLock的功能和使用
2022-11-13

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录