经典面试题——让你设计一个限流的系统怎么做?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了经典面试题——让你设计一个限流的系统怎么做?相关的知识,希望对你有一定的参考价值。
参考技术A 保障服务稳定的三大利器:熔断降级、服务限流和故障模拟。限流系统是当前很多系统都需要考虑的场景。首先在nginx层面是可以做限流的,除此之外,在微服务层面还是有很多空间可以施展的。限流的话,主要思路分为 请求数量限制 和 消费能力限制 两类。前者主要是限制一段时间内的总并发数、后者主要是限制消费者的消费能力。
限流算法
限流算法来说,主要包含令牌桶算法、漏桶算法和计数器等。 对于简单的计数器算法 ,通过AtomicLong#incrementAndGet()来进行粗暴的控制,因为容易导致“突刺现象”(比如单位时间1s内的前10ms,已经通过了100个请求,那后面的990ms,只能拒绝), 所以这里不做推荐 。
令牌桶算法
令牌工厂:匀速生成令牌
令牌桶:拥有固定的令牌数
应用者:一次可以申请N个令牌,没有令牌不能进行后续处理。
如果使用Redis来实现的话会比较简单,大概思路如下:
1/ 获取令牌:依靠List的leftPop来获取令牌
Objectresult = redisTemplate.opsForList().leftPop("limit_list");
2/ 向令牌桶添加令牌
redisTemplate.opsForList().rightPush("limit_list",UUID.randomUUID().toString());
漏桶算法
漏桶:容量固定
流速:任意
流出水滴:固定速率
滑动窗口
用Redis的list数据结构可以轻而易举的实现该功能:保证每N秒内至多M个请求,缺点就是zset的数据结构会越来越大。实现方式相对也是比较简单的。
1/ 请求进来:UUID生成唯一的value;score用当前的时间戳
redisTemplate.opsForZSet().add("limit",UUID.randomUUID().toString(),currentTime);
2/ 限流:zset的range方法可以统计两个时间戳内的请求,达到限流效果
Integercount = redisTemplate.opsForZSet().rangeByScore("limit", currentTime -
以上是关于经典面试题——让你设计一个限流的系统怎么做?的主要内容,如果未能解决你的问题,请参考以下文章