使用Java实现Redis限流的方法

作者:别团等shy哥发育 时间:2023-09-27 01:43:47 

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容器。

使用Java实现Redis限流的方法

使用Java实现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限流的方法

来源:https://blog.csdn.net/qq_43753724/article/details/120456516

标签:Java,Redis,限流
0
投稿

猜你喜欢

  • Hibernate中的多表查询及抓取策略

    2022-02-22 18:58:28
  • Java设计模式之桥接模式的实现

    2021-10-18 20:29:04
  • SpringBoot整合screw实现数据库文档自动生成的示例代码

    2023-11-29 05:30:15
  • 深入理解C#中常见的委托

    2022-03-23 01:05:46
  • Android中NestedScrolling滑动机制详解

    2022-09-16 22:32:13
  • C语言函数超详细讲解上篇

    2022-05-23 06:29:31
  • Java Socket编程(五) 简单的WEB服务器

    2023-05-23 01:00:04
  • Android 仿苹果IOS6开关按钮

    2023-11-21 15:16:08
  • JAVA swing布局管理器实例解析

    2022-01-11 05:05:15
  • C#编程中使用设计模式中的原型模式的实例讲解

    2023-07-18 07:47:10
  • Java Web实现添加定时任务的方法示例

    2023-11-25 02:12:15
  • Android利用Canvas标点画线并加入位移动画(2)

    2022-04-09 07:57:02
  • Unity实现游戏存档框架

    2023-02-10 13:05:15
  • 详解Kotlin Android开发中的环境配置

    2022-06-25 10:42:17
  • Android 自定义 Toast 显示时间

    2022-01-22 23:22:06
  • Java实现的上传并压缩图片功能【可等比例压缩或原尺寸压缩】

    2023-03-17 11:09:11
  • 教你怎么用java一键自动生成数据库文档

    2021-08-01 02:34:36
  • Java中常见的查找算法与排序算法总结

    2021-07-14 13:21:23
  • springboot对压缩请求的处理方法

    2022-02-11 14:00:59
  • Java反射机制(Reflection)浅析

    2023-04-17 14:35:56
  • asp之家 软件编程 m.aspxhome.com