分布式限流zookeeper,分布式限流实现
终极管理员 知识笔记 80阅读
目录

1:如何实现分布式限流
2:限流的几种类别

2.1:固定窗口限流
2.2:滑动窗口限流
2.3:漏桶限流
2.4:令牌桶限流
3:实现分布式限流:Redis
3.1:引入Redisson的依赖包
3.2:初始化Redisson
3.3:创建Redisson的限流类
1:如何实现分布式限流
1:把统计用户的使用频率等这些数据放到一个集中的存储比如redis这样无论用户的请求落在了哪台服务器都以集中存储的数据为准。(Redis)
2:限流的几种类别 2.1:固定窗口限流单位时间内允许部分操作。 1小时只允许10个用户操作。
优点:最简单
缺点:可能出现流量突刺
eg:前59分钟第59分钟来了十个操作。第一小时01分钟又来了十个操作就可能导致流量突刺相当于2分钟实现了20个操作。
2.2:滑动窗口限流单位时间内允许部分操作但是这个时间是滑动的 需要指定滑动单位
滑动单位: 1min
开始前:
0s 1h 2h
一分钟:
1min 1h1min
优点;能够解决上面流量突刺的问题第59分钟限流窗口59min到1h59min,这个时间段内接受10次请求只要在这个窗口内更多的操作就会被拒绝。
缺点:实现相对复杂。滑动单位越小,限效果越好。
2.3:漏桶限流以固定的速率请求当请求桶满后拒绝请求。
每秒处理10个请求桶的容量是10每0.1秒处理1次请求(固定的)如果1秒内来了10个都可以处理完但如果一秒内来了11个请求最后那个请求就会被拒绝。
优点:能够一定程度上应对流量突刺能够以固定的速率处理请求安全性高
缺点:速度是固定的没有办法处理一批请求只能一个一个来
2.4:令牌桶限流管理员先生成一批令牌每秒生成10个令牌当用户操作前先去拿到令牌有令牌的人可以先执行都能够同时执行。
优点:能够并发处理同时的请求并发性高
缺点:时间单位选取的问题。
以上漏桶限流和令牌桶限流最常用。
3:实现分布式限流:Redis 3.1:引入Redisson的依赖包 <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.17.5</version> </dependency>
3.2:初始化Redisson ConfigurationConfigurationProperties(prefix spring.redis)public class RedissonConfig { private Integer database; private String host; private String port; Bean public RedissonClient getRedissonClient(){ //配置Redis的配置类 Config confignew Config(); config.useSingleServer() .setDatabase(database) .setAddress(redis://host:port); RedissonClient redisson Redisson.create(config); return redisson; }}
3.3:创建Redisson的限流类
Servicepublic class RedisLimiterManage { Autowired private RedissonClient redissonClient; //key:区分不同的限流器:不同的用户id public void doRateLimit(String key){ RRateLimiter rateLimiterredissonClient.getRateLimiter(key); //将所有用户的访问次数放在同一个限流器上,1秒允许两次 rateLimiter.trySetRate(RateType.OVERALL,2,1, RateIntervalUnit.SECONDS); //每当一个用户来了之后请求一个令牌 boolean result rateLimiter.tryAcquire(1); if(!result){ throw new BusinessException(ErrorCode.NO_AUTH_ERROR,请求过于频繁); } }}
当我们使用分布式限流Redis的时候只需要让这个RedisLimiterManage调用doRateLimit方法就可以进行分布式限流的操作。
Autowired private RedisLimiterManage redisLimiterManage;//引入依赖 //进行限流判断 redisLimiterManage.doRateLimit(genChartByAi_user.getId()); //每个用户的限流器