17 高并发之限流

作者: 十丈_红尘 | 来源:发表于2018-11-03 14:46 被阅读183次

郑重说明:尽管网络上有很多的资源可以借鉴,但是笔者还是需要很多的帮助才能写出这些总结笔记
1️⃣首先也是最重要的慕课网给了我巨大的帮助,自从第一次打开慕课网以后,从此就在我心里播下了一颗学习的种子;
2️⃣要特别鸣谢慕课网的Jimin老师,从他那里我"偷了"许多的想法放到这篇笔记里边;
3️⃣本文内容直接出自Jimin老师的课程Java并发编程与高并发解决方案
4️⃣清醒时做事,糊涂时学习,祝大家都能梦想成真;


1️⃣概念

限流就是通过对并发访问/请求进行限速或一个时间窗口内的请求进行限速,从而达到保护系统的目的。一般系统可以通过压测来预估能处理的峰值,一旦达到设定的峰值阀值,则可以拒绝服务(定向错误页或告知资源没有了)、排队或等待(例如:秒杀、评论、下单)、降级(返回默认数据)
限流不能乱用,否则正常流量会出现一些奇怪的问题,从而导致用户抱怨。


2️⃣限流场景模拟

假设有130W到140W的数据插入到数据库中,如果没有做限流,数据库的主库会突然接收到130w的插入操作
首先是网络上的开销,很可能直接把带宽占满,导致其他请求无法正常传输和处理,其次会是数据库的负载突然增高,导致无法处理某些数据库的操作,也有可能数据库没有足够的连接导致某些数据库插入查询失败;
还有一点就是现在数据库都做了主从设计,主数据库的数据还要同步给从库,这时瞬间插入了大量的数据,会带来从库和主库的延迟特别大,这时从库查询不准确的概率也会跟着提升。
如果我们放慢插入数据库的速度,这时插入数据库主库的速率会很正常,同步到从库也很正常。网络消耗也可以接收不会影响其他服务。


3️⃣应用限流算法

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

这个方法有一个致命问题:临界问题——当遇到恶意请求,在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,请求无法通过。

4️⃣限流算法代码实现
1 单机限流
// 令牌桶算法实现 tryAcquire
@Slf4j
public class RateLimiterExample1 {

    private static RateLimiter rateLimiter = RateLimiter.create(5);

    public static void main(String[] args) throws Exception {

        for (int index = 0; index < 100; index++) {
            if (rateLimiter.tryAcquire(190, TimeUnit.MILLISECONDS)) {
                handle(index);
            }
        }
    }

    private static void handle(int i) {
       log.info("{}", i);
    }
}
// 令牌桶算法实现 acquire
@Slf4j
public class RateLimiterExample2 {

    private static RateLimiter rateLimiter = RateLimiter.create(5);

    public static void main(String[] args) throws Exception {

        for (int index = 0; index < 100; index++) {
            rateLimiter.acquire();
            handle(index);
        }
    }

    private static void handle(int i) {
       log.info("{}", i);
    }
}
2 分布式限流

建议使用Redis实现,也可以根据总限流数实现;

相关文章

  • 分布式系统

    聊聊高并发系统之限流特技

  • 17 高并发之限流

    郑重说明:尽管网络上有很多的资源可以借鉴,但是笔者还是需要很多的帮助才能写出这些总结笔记1️⃣首先也是最重要的慕课...

  • 高并发之限流

    原创:高并发之限流[https://hexo.yuanjh.cn/hexo/e622532d/] 高并发系统设...

  • 聊聊高并发系统限流特技-2

    转载来自开涛的聊聊高并发系统限流特技-2 上一篇《聊聊高并发系统限流特技-1》讲了限流算法、应用级限流、分布式限流...

  • 高并发之限流

    目录 概念 划分 线上情况 概念 在开发分布式高并发系统时有三把利器用来保护系统:缓存、降级、限流。其中降级的一种...

  • 限流熔断特技之深入理解

    聊聊高并发系统之限流特技 https://www.iteye.com/blog/jinnianshilongnia...

  • 高并发之限流算法及实现

    本文参考资料 高并发系统之限流特技:http://blog.csdn.net/g_hongjin/article/...

  • 限流、熔断、降级

    一、限流、熔断、降级概念 1.1 限流: 在高并发系统中一定要用,高并发的所有请求进来,不是让每个请求都打到后台集...

  • 高并发环境下的限流策略

    本文将从以下几个方面分析限流策略: 什么是限流限流算法限流算法的应用 什么是限流 在开发高并发系统时,有很多手段来...

  • 聊聊高并发系统之限流特技-2

    摘要:上一篇《聊聊高并发系统限流特技-1》讲了限流算法、应用级限流、分布式限流;本篇将介绍接入层限流实现。 接入层...

网友评论

    本文标题:17 高并发之限流

    本文链接:https://www.haomeiwen.com/subject/pgukxqtx.html