Redis的zset集合实现限流

	Redis的zset是有序集合,可以实现简单的限流功能,大致思路如下:
 /**
     * 1、先通过zadd方法把表示操作类型的key作为键插入有序集合,插入时用表示当前时间的currentTime作为值,以保证值的唯一性,同时用currentTime作为有序集合里元素的score值。
     * 2、随后通过zremrangeByScore命令去除0到距当前时间limitTime时间范围内的数据,
     * 那么通过zremrangeByScore命令就能在有序集合里去除score范围从0到距离当前限定时间的数据,这样就能确保有序集合内只存有指定时间内的元素。
     * 3、用zcard命令统计有序集合内键为key的个数,判断集合大小是否已经超过指定限流次数,确定是否需要限流。
     * 4、最后,使用expire语句设置有序集合里相关键的超时时间,这样就能确保在限流动作完成后这些键能自动删除,避免内存溢出。
     *
     * @param jedis     redis 对象
     * @param key      redis---键(key)
     * @param time    限制时间 秒(s)
     * @param num    限制次数
     */
    public static boolean canPass(ShardedJedis jedis, String key, int time, int num) {
        long currentTime = System.currentTimeMillis();
        //把请求放入zset(有序集合)
        jedis.zadd(key, currentTime, String.valueOf(currentTime));
        //去掉时间范围外(超时)的请求
        jedis.zremrangeByScore(key, 0, currentTime - time * 1000);
        //统计时间范围内总数
        Long count = jedis.zcard(key);
        //设置所有请求的超时时间
        jedis.expire(key, time + 1);
        boolean flag = num >= count;
        return flag;
    }

    /**
     * 获取token (使用redis的zset特性限流)
     *
     * @param username 用户名
     * @param sign     签名
     * @return
     */
    @PostMapping("/getToken")
    public StandardResult getToken(final ServerWebExchange exchange, String username, String sign) {
        ShardedJedis jedis = shardedJedisPool.getResource();
        //先判断该用户是否需要进行限流 (10秒内同一用户获取token次数不能超过三次)
        boolean requestType = canPass(jedis, username, 10, 3);
        if(requestType){
            //获取token业务代码......
            return StandardResult.ok(token);
        }else {
            return StandardResult.loginFailed("当前用户获取token次数过多,请稍后再试!");
        }
    }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值