基于redis的限流


/**
* 基于redis的限流
* @author: whh
* @date: 2020.03.19
**/

public class RedisRateLimitUtil {
public static final Logger LOGGER = LoggerFactory.getLogger(RedisRateLimitUtil.class);

    @Resource(name = "anticheatRedisClient")
    private RedisClient anticheatRedisClient;

    public boolean tryAcquire(String key, int timeWindow, int limitNum) {
        boolean acquireResult = anticheatRedisClient.execute(key, new JedisAction<Boolean>() {
            @Override
            public Boolean action(Jedis jedis) {
                try {
                    String setNxResult = jedis.set(key, "1", "NX", "EX", timeWindow);
                    if ("OK".equals(setNxResult)) {
                        return true;
                    }
                    Long num = jedis.incr(key);
                    if (num == 1) {
                        jedis.expire(key, timeWindow);
                    }
                    if (num > limitNum) {
                        return false;
                    }
                    return true;
                } catch (Exception e) {
                    LOGGER.error("acquireResult error", e);
                }
                return true;
            }
        });
        return acquireResult;
    }
}

 常用的限流算法有哪些?

1、计数器固定窗口算法

   没到阈值,接受请求,计数器+1,超过时间窗口,计数器设为0重新开始计数。

   缺点:存在突刺现象,不够平滑。

2、滑动窗口算法

   一个时间窗口划分成多个时间窗口,当请求时间大于窗口最大时间,向前平移,丢弃第一个窗口数据,第二个窗口变为第一个,在最后新增一个窗口。

3、漏斗算法

    将所有请求放到一个大桶里,由桶匀速处理。

    请求量过大超过桶大小,会被丢弃,限制访问速度可保护自身系统。

4、令牌桶算法

    先匀速生成令牌,放入桶中,请求来了取令牌,取到则执行。  

    限制平均速度的情况下可以允许一定程度的流量突发。

 

posted @ 2020-03-18 16:47  提拉米苏007  阅读(263)  评论(1编辑  收藏  举报