ITPub博客

首页 > 数据库 > 数据库开发技术 > 一看就懂的java限流策略

一看就懂的java限流策略

原创 数据库开发技术 作者:毛毛小妖的笔记 时间:2019-04-06 23:36:14 0 删除 编辑


在大数据量高并发访问时,经常会出现服务或接口面对暴涨的请求而不可用的情况,甚至引发连锁反映导致整个系统崩溃。此时你需要使用的技术手段之一就是限流,当请求达到一定的并发数或速率,就进行等待、排队、降级、拒绝服务等。在限流时,有四种算法,分别是:计数器法、滑动窗口法、漏桶算法和令牌桶算法。

一、算法原理

① 计数器法

有时我们还会使用计数器来进行限流,主要用来限制一定时间内的总并发数,比如数据库连接池、线程池、秒杀的并发数;计数器限流只要一定时间内的总请求数超过设定的阀值则进行限流,是一种简单粗暴的总数量限流,而不是平均速率限流

这个方法有一个致命问题:临界问题——当遇到恶意请求,在0:59时,瞬间请求100次,并且在1:00请求100次,那么这个用户在1秒内请求了200次,用户可以在重置节点突发请求,而瞬间超过我们设置的速率限制,用户可能通过算法漏洞击垮我们的应用。


② 滑动窗口

在上图中,整个红色矩形框是一个时间窗口,在我们的例子中,一个时间窗口就是1分钟,然后我们将时间窗口进行划分,如上图我们把滑动窗口

划分为6格,所以每一格代表10秒,每超过10秒,我们的时间窗口就会向右滑动一格,每一格都有自己独立的计数器,例如:一个请求在0:35到达,

那么0:30到0:39的计数器会+1,那么滑动窗口是怎么解决临界点的问题呢?如上图,0:59到达的100个请求会在灰色区域格子中,而1:00到达的请求

会在红色格子中,窗口会向右滑动一格,那么此时间窗口内的总请求数共200个,超过了限定的100,所以此时能够检测出来触发了限流。

回头看看计数器算法,会发现,其实计数器算法就是窗口滑动算法,只不过计数器算法没有对时间窗口进行划分,所以是一格。

由此可见,当滑动窗口的格子划分越多,限流的统计就会越精确。

③ 漏桶算法

这个算法很简单。首先,我们有一个固定容量的桶,有水进来,也有水出去。对于流进来的水,我们无法预计共有多少水流进来,也无法预计流水速度,但
对于流出去的水来说,这个桶可以固定水流的速率,而且当桶满的时候,多余的水会溢出来。

④ 令牌桶算法

从上图中可以看出,令牌算法有点复杂,桶里存放着令牌token。桶一开始是空的,token以固定的速率r往桶里面填充,直到达到桶的容量,多余的token会
被丢弃。每当一个请求过来时,就会尝试着移除一个token,如果没有token,请求无法通过。

二、算法实现

1、令牌桶算法

  1. public class RateLimiterDemo {

  2. private static RateLimiter limiter = RateLimiter.create(5);


  3. public static void exec() {

  4. limiter.acquire(1);

  5. try {

  6. // 处理核心逻辑

  7. TimeUnit.SECONDS.sleep(1);

  8. System.out.println("--" + System.currentTimeMillis() / 1000);

  9. } catch (InterruptedException e) {

  10. e.printStackTrace();

  11. }

  12. }

  13. }

2、计数器限流

  1. public class CountRateLimiterDemo2 {


  2. private static Semaphore semphore = new Semaphore(5);


  3. public static void exec() {

  4. if(semphore.getQueueLength()>100){

  5. System.out.println("当前等待排队的任务数大于100,请稍候再试...");

  6. }

  7. try {

  8. semphore.acquire();

  9. // 处理核心逻辑

  10. TimeUnit.SECONDS.sleep(1);

  11. System.out.println("--" + System.currentTimeMillis() / 1000);

  12. } catch (InterruptedException e) {

  13. e.printStackTrace();

  14. } finally {

  15. semphore.release();

  16. }

  17. }

  18. }

3、分布式限流

建议使用Redis实现。也可以根据总限流数实现,比如总限流400,两台机器的话一台限流200。

原文作者:毛毛小妖的笔记;如有侵权,请联系管理员删除。

下一篇: 没有了~
请登录后发表评论 登录
全部评论

注册时间:2019-04-04

  • 博文量
    70
  • 访问量
    46583