使用Java实现Redis限流的方法

1、概述

  限流的含义是在单位时间内确保发往某个模块的请求数量小于某个数值,比如在实现秒杀功能时,需要确保在10秒内发往支付模块的请求数量小于500个。限流的作用是防止某个段时间段内的请求数过多,造成模块因高并发而不可用。

2、zset有序集合相关命令与限流

  zset也叫有序集合,是Redis的一种数据类型,在其中每个值(value)都会有一个对应的score参数,以此来描述该值的权重分值。可以通过如下形式的命令向zset有序集合里添加元素:

zadd key score value

  在限流相关的应用里,可以通过zadd命令往有序集合里存放数据时引入表示权重的score参数,并在其中存放时间戳。由于zset是有序集合,因此包含时间戳的score能被排序,这样就能用zremrangeByScore命令去除指定时间范围内的数据。zrenrabgeByScore命令的语法如下:

zremrangeByScore key min max

  通过该命令能在有序集合里删除键为key、score值在min到max范围内的数据。通过这种删除动作,能排除限流时间范围外的数据,并能在此基础上通过zcard命令统计有序集合内元素的数量,以确保请求数量小于限流的上限值。zcard命令的语法格式如下:

zcard key

  该命令会返回有序集合内指定key的元素数量。

3、zset有序结合与限流

有关redis启动的知识不做过多介绍了,这里我用docker创建的redis容器。

本例实现100秒内只能处理3个请求

LimitRequest.java

package com.baizhi.request;

import redis.clients.jedis.Jedis;

public class LimitRequest {
    public static void main(String[] args) {
        Jedis jedis=new Jedis("192.168.159.33",6379);
        jedis.del("PayRequest");
        //模拟发5个请求
        int cnt=5;
        for (int i = 0; i < cnt; i++) {
            LimitUtil.canVisit(jedis,"PayRequest",100,3);
        }
    }
}
class LimitUtil{
    //判断是否需要限流
    public static void canVisit(Jedis jedis,String requestType,int limitTime,int limitNum){
        long currentTime=System.currentTimeMillis();
        //把请求放入zset
        jedis.zadd(requestType,currentTime,Long.valueOf(currentTime).toString());
        //去掉时间范围外(超时)的请求
        jedis.zremrangeByScore(requestType,0,currentTime-limitTime*1000);
        //统计时间范围内总数
        Long count=jedis.zcard(requestType);
        //设置所有请求的超时时间
        jedis.expire(requestType,limitTime+1);
        boolean flag=limitNum>=count;
        if(flag){
            System.out.println("Can visit");
        }else{
            System.out.println("Can not visit");
        }
    }
}

  先通过zadd方法把表示操作类型的requestType作为键插入有序集合,插入时用表示当前时间的currentTime作为值,以保证值的唯一性,同时用currentTime作为有序集合里元素的score值。
   随后通过zremrangeByScore命令去除0到距当前时间limitTime时间范围内的数据。比如限流的时间范围是100秒,那么通过zremrangeByScore命令就能在有序集合里去除score范围从0到距离当前时间100秒的数据,这样就能确保有序集合内只存有最近100秒内发来的元素。
  其中,用zcard命令统计有序集合内键为requestType的个数,如果通过if语句发现当前个数还没有达到限流的上限,则允许该请求方法,否则不允许。这里通过最后的打印语句来模拟“是否允许请求访问”的动作。
  同时请注意,需要使用expire语句设置有序集合里相关键的超时时间,这样就能确保在限流动作完成后这些键能自动删除,而不是一致驻留在内存中。
  在main函数里,首先创建指向虚拟机6379端口的jedis对象,为了确保在多次运行时数据不相互干扰,在运行前通过del语句删除相关的键。
   随后使用for循环里通过调用canVisit方法模拟发出5个请求。在调用该方法时,通过传入参数指定限流所用的键为"PayRequest",同时指定了100秒内只能处理3个请求。运行之后控制台的效果如下:

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

(0)

相关推荐

  • Java之理解Redis回收算法LRU案例讲解

    如何通俗易懂的理解LRU算法? 1.LRU是什么? LRU全称Least Recently Used,也就是最近最少使用的意思,是一种内存管理算法,最早应用于Linux操作系统. LRU算法基于一种假设:长期不被使用的数据,在未来被用到的几率也不大.因此,当数据所占内存达到一定阈值时,我们要移除掉最近最少被使用的数据. LRU算法应用:可以在内存不够时,从哈希表移除一部分很少访问的用户. LRU是什么?按照英文的直接原义就是Least Recently Used,最近最久未使用法,它是按照一个非

  • Java之操作Redis案例讲解

    首先 下载 jedis.jar包 然后再 工程设置里面找到Libraries,点击+.添加下载好的jedis.jar包.点击OK退出即可 创建Java_Control_Redis类 测试链接 package ccit.redis; import redis.clients.jedis.Jedis; public class Java_Control_Redis { public static void main(String[] args) { //连接本地的 Redis 服务 Jedis je

  • java 用redisTemplate 的 Operations存取list集合操作

    java redisTemplate 的 Operations存取list集合 一 .存取为list类型 @RestController @RequestMapping("/test") @Slf4j public class TestController { @Autowired private RedisTemplate redisTemplate; @ApiOperation("redis-savelist") @PostMapping("/redi

  • Java实现RedisUtils操作五大集合(增删改查)

    前排提示,我在这个工具类加了@Component注解,如果在springboot的项目使用,记得通过@Autowired注入使用. import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.*; import org.springframework.stereotype.Component; import java.io.Serializabl

  • 浅谈java如何实现Redis的LRU缓存机制

    目录 LRU概述 使用LinkedHashMap实现 使用LinkedHashMap简单方法实现 双链表+hashmap LRU概述 最近使用的放在前面,最近没用的放在后面,如果来了一个新的数,此时内存满了,就需要把旧的数淘汰,那为了方便移动数据,肯定就得使用链表类似的数据结构,再加上要判断这条数据是不是最新的或者最旧的那么应该也要使用hashmap等key-value形式的数据结构. 使用LinkedHashMap实现 package thread; import java.util.Link

  • Java实现Redis延时消息队列

    目录 什么是延时任务 延时任务的特点 实现思路: 代码实现 1.消息模型 2.RedisMq 消息队列实现类 3.消息生产者 4.消息消费者 5. 消息执接口 6. 任务类型的实现类:可以根据自己的情况去实现对应的队列需求 什么是延时任务 延时任务,顾名思义,就是延迟一段时间后才执行的任务.举个例子,假设我们有个发布资讯的功能,运营需要在每天早上7点准时发布资讯,但是早上7点大家都还没上班,这个时候就可以使用延时任务来实现资讯的延时发布了.只要在前一天下班前指定第二天要发送资讯的时间,到了第二天

  • 使用Java实现Redis限流的方法

    1.概述   限流的含义是在单位时间内确保发往某个模块的请求数量小于某个数值,比如在实现秒杀功能时,需要确保在10秒内发往支付模块的请求数量小于500个.限流的作用是防止某个段时间段内的请求数过多,造成模块因高并发而不可用. 2.zset有序集合相关命令与限流   zset也叫有序集合,是Redis的一种数据类型,在其中每个值(value)都会有一个对应的score参数,以此来描述该值的权重分值.可以通过如下形式的命令向zset有序集合里添加元素: zadd key score value   

  • 详解Java分布式IP限流和防止恶意IP攻击方案

    前言 限流是分布式系统设计中经常提到的概念,在某些要求不严格的场景下,使用Guava RateLimiter就可以满足.但是Guava RateLimiter只能应用于单进程,多进程间协同控制便无能为力.本文介绍一种简单的处理方式,用于分布式环境下接口调用频次管控. 如何防止恶意IP攻击某些暴露的接口呢(比如某些场景下短信验证码服务)?本文介绍一种本地缓存和分布式缓存集成方式判断远程IP是否为恶意调用接口的IP. 分布式IP限流 思路是使用redis incr命令,完成一段时间内接口请求次数的统

  • SpringBoot服务上实现接口限流的方法

    Sentinel是阿里巴巴开源的限流器熔断器,并且带有可视化操作界面. 在日常开发中,限流功能时常被使用,用于对某些接口进行限流熔断,譬如限制单位时间内接口访问次数:或者按照某种规则进行限流,如限制ip的单位时间访问次数等. 之前我们已经讲过接口限流的工具类ratelimter可以实现令牌桶的限流,很明显sentinel的功能更为全面和完善.来看一下sentinel的简介: https://github.com/spring-cloud-incubator/spring-cloud-alibab

  • redis限流的实际应用

    为什么要做限流 首先让我们先看一看系统架构设计中,为什么要做"限流". 旅游景点通常都会有最大的接待量,不可能无限制的放游客进入,比如故宫每天只卖八万张票,超过八万的游客,无法买票进入,因为如果超过八万人,景点的工作人员可能就忙不过来,过于拥挤的景点也会影响游客的体验和心情,并且还会有安全隐患:「只卖N张票,这就是一种限流的手段」. 软件架构中的服务限流也是类似,也是当系统资源不够的时候,已经不足以应对大量的请求,为了保证服务还能够正常运行,那么按照规则,「系统会把多余的请求直接拒绝掉

  • 详解5种Java中常见限流算法

    目录 01固定窗口 02滑动窗口 03漏桶算法 04令牌桶 05滑动日志 06分布式限流 07总结 1.瞬时流量过高,服务被压垮? 2.恶意用户高频光顾,导致服务器宕机? 3.消息消费过快,导致数据库压力过大,性能下降甚至崩溃? ...... 在高并发系统中,出于系统保护角度考虑,通常会对流量进行限流:不但在工作中要频繁使用,而且也是面试中的高频考点. 今天我们将图文并茂地对常见的限流算法分别进行介绍,通过各个算法的特点,给出限流算法选型的一些建议,并给出Java语言实现的代码示例. 01固定窗

  • Nginx使用limit_req_zone对同一IP访问进行限流的方法

    nginx可以使用ngx_http_limit_req_module模块的limit_req_zone指令进行限流访问,防止用户恶意攻击刷爆服务器.ngx_http_limit_req_module模块是nginx默认安装的,所以直接配置即可. 首先,在nginx.conf文件中的http模块下配置 limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; 说明:区域名称为one(自定义),占用空间大小为10m,平均处理的请求频率不能超

  • Java实现接口限流方案

    本文实例为大家分享了Java实现接口限流方案的具体代码,供大家参考,具体内容如下 RateLimiter Google开源工具包Guava提供了限流工具类RateLimiter,基于令牌桶算法实现. 1.maven依赖: <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>27.1-jre</versio

  • Redis限流的几种实现

    目录 一.简单的限流 基本原理 二.漏斗限流 基本原理 Redis-Cell 参考来源 一.简单的限流 基本原理 当系统处理能力有限,如何组织计划外的请求对系统施压.首先我们先看下一些简单的限流策略,防止暴力攻击.比如要对IP访问,没5s只能访问10次,超过进行拦截. 如上图,一般使用滑动窗口来统计区间时间内的访问次数. 使用 zset 记录 IP 访问次数,每个 IP 通过 key 保存下来,score 保存当前时间戳,value 唯一用时间戳或者UUID来实现 代码实现 public cla

  • Java 常见的限流算法详细分析并实现

    目录 为什么要限流 限流算法 计数器限流 漏桶限流 令牌桶限流 为什么要限流 在保证可用的情况下尽可能多增加进入的人数,其余的人在排队等待,或者返回友好提示,保证里面的进行系统的用户可以正常使用,防止系统雪崩. 限流算法 限流算法很多,常见的有三类,分别是 计数器算法 .漏桶算法.令牌桶算法 . (1)计数器:           在一段时间间隔内,处理请求的最大数量固定,超过部分不做处理. (2)漏桶:           漏桶大小固定,处理速度固定,但请求进入速度不固定(在突发情况请求过多时

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

    限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务. 前几天在DD的公众号,看了一篇关于使用 瓜娃 实现单应用限流的方案 -->原文,参考<redis in action> 实现了一个jedis版本的,都属于业务层次限制. 实际场景中常用的限流策略: Nginx接入层限流 按照一定的规则如帐号.IP.系统调用逻辑等在Nginx层面做限流 业务应用系统限流 通过业务代码控制流量这个流量可以被称为信号量,可以理解成是一种锁,它

随机推荐