springboot高级教程基于 redis 通过注解实现限流

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: springboot高级教程基于 redis 通过注解实现限流

Spring Boot整合Redis有一种方便的方式是使用注解方式实现限流。


可以通过自定义注解的方式来标注需要限流的方法,在方法执行前进行限流的检查。


以下是具体实现方式:


1. 自定义注解`@RedisLimit`,并定义注解元素,如限流的时间、限流的次数等。

2. 编写切面类`RedisLimitAspect`,在方法执行前调用`RedisLimit`组件实现限流。

3. 将`RedisLimitAspect`类加入Spring容器中,以便进行注入。

4. 在需要进行限流的方法上添加`@RedisLimit`注解。


以下是示例代码:


`@RedisLimit`注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisLimit {
    int limit() default 10;
    int timeout() default 60;
    String key() default "";
}


切面类`RedisLimitAspect`:


    @Aspect
    @Component
    public class RedisLimitAspect {
        @Autowired
        private RedisTemplate<String, String> redisTemplate;
        @Pointcut("@annotation(redisLimit)")
        public void pointcut(RedisLimit redisLimit) {}
        @Before("pointcut(redisLimit)")
        public void before(JoinPoint joinPoint, RedisLimit redisLimit) throws Throwable {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                    .getRequest();
            String ip = IpUtils.getRequestIp(request);
            String key = redisLimit.key().equals("") ? ip : redisLimit.key();
            int limit = redisLimit.limit();
            int timeout = redisLimit.timeout();
            if (!redisLimit(redisTemplate, key, limit, timeout)) {
                throw new RuntimeException("限流了");
            }
        }
        /**
         * 判断Redis中的key对应的值,是否满足小于limit
         *
         * @param redisTemplate RedisTemplate
         * @param key           键
         * @param limit         限流次数
         * @param timeout       超时时间(秒)
         * @return 是否限流
         */
        private boolean redisLimit(RedisTemplate<String, String> redisTemplate, String key, int limit, int timeout) {
            String value = String.valueOf(System.currentTimeMillis() / 1000);
            try {
                redisTemplate.watch(key);
                List<String> list = redisTemplate.opsForList().range(key, 0, -1);
                int count = 0;
                if (list != null && !list.isEmpty()) {
                    for (String time : list) {
                        if (Long.parseLong(time) >= (System.currentTimeMillis() / 1000 - timeout)) {
                            count++;
                        } else {
                            redisTemplate.opsForList().trim(key, count, -1);
                            break;
                        }
                    }
                }
                if ((count + 1) > limit) {
                    return false;
                }
                redisTemplate.multi();
                redisTemplate.opsForList().rightPush(key, value);
                redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
                redisTemplate.exec();
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            } finally {
                redisTemplate.unwatch();
            }
            return true;
        }
    }


    在需要进行限流的方法上添加`@RedisLimit`注解:


      @RestController
      public class TestController {
          @GetMapping("/test")
          @RedisLimit(key = "testKey", limit = 5, timeout = 60)
          public String test() {
              return "success";
          }
      }


      注意:在使用`@RedisLimit`注解时,每个方法对应的key不应该相同,否则会出现相互干扰的情况。

      相关实践学习
      基于Redis实现在线游戏积分排行榜
      本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
      云数据库 Redis 版使用教程
      云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
      目录
      相关文章
      |
      11天前
      |
      缓存 NoSQL Java
      Spring Boot与Redis:整合与实战
      【10月更文挑战第15天】本文介绍了如何在Spring Boot项目中整合Redis,通过一个电商商品推荐系统的案例,详细展示了从添加依赖、配置连接信息到创建配置类的具体步骤。实战部分演示了如何利用Redis缓存提高系统响应速度,减少数据库访问压力,从而提升用户体验。
      31 2
      |
      19天前
      |
      JSON NoSQL Java
      springBoot:jwt&redis&文件操作&常见请求错误代码&参数注解 (九)
      该文档涵盖JWT(JSON Web Token)的组成、依赖、工具类创建及拦截器配置,并介绍了Redis的依赖配置与文件操作相关功能,包括文件上传、下载、删除及批量删除的方法。同时,文档还列举了常见的HTTP请求错误代码及其含义,并详细解释了@RequestParam与@PathVariable等参数注解的区别与用法。
      |
      18天前
      |
      NoSQL Java Redis
      shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
      这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
      21 0
      shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
      |
      13天前
      |
      存储 NoSQL Unix
      Redis 教程
      10月更文挑战第13天
      24 0
      |
      13天前
      |
      NoSQL 安全 Redis
      AWS迁移教程,Redis迁移到Elasticache
      AWS迁移教程,Redis迁移到Elasticache
      |
      25天前
      |
      存储 缓存 NoSQL
      数据的存储--Redis缓存存储(一)
      数据的存储--Redis缓存存储(一)
      60 1
      |
      25天前
      |
      存储 缓存 NoSQL
      数据的存储--Redis缓存存储(二)
      数据的存储--Redis缓存存储(二)
      37 2
      数据的存储--Redis缓存存储(二)
      |
      22天前
      |
      消息中间件 缓存 NoSQL
      Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
      【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
      56 6
      |
      26天前
      |
      缓存 NoSQL 关系型数据库
      redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿
      本文深入探讨了Redis缓存的相关知识,包括缓存的概念、使用场景、可能出现的问题(缓存预热、缓存穿透、缓存雪崩、缓存击穿)及其解决方案。
      127 0
      redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿
      |
      2天前
      |
      存储 缓存 监控
      利用 Redis 缓存特性避免缓存穿透的策略与方法
      【10月更文挑战第23天】通过以上对利用 Redis 缓存特性避免缓存穿透的详细阐述,我们对这一策略有了更深入的理解。在实际应用中,我们需要根据具体情况灵活运用这些方法,并结合其他技术手段,共同保障系统的稳定和高效运行。同时,要不断关注 Redis 缓存特性的发展和变化,及时调整策略,以应对不断出现的新挑战。
      21 10