四种分布式限流算法实现!

大家好 , 我是老三 , 最近公司在搞年终大促 , 随着各种营销活动“组合拳”打出 , 进站流量时不时会有一个小波峰 , 一般情况下 , 当然是流量越多越好 , 前提是系统能杠地住 。大家都知道 , 一个分布式系统 , 有两个“弃车保帅”的策略:限流和熔断 , 这期 , 我们就来讨论一下分布式系统的限流 。
探探限流带着问题走近限流为什么要限流呢?就像我上面说的 , 流量多 , 的确是一件好事 , 但是如果过载 , 把系统打挂了 , 那大家都要吃席了 。
没逝吧
所以 , 在各种大促活动之前 , 要对系统进行压测 , 评估整个系统的峰值QPS , 要做一些限流的设置 , 超过一定阈值 , 就拒绝处理或者延后处理 , 避免把系统打挂的情况出现 。
限流和熔断有什么区别?限流发生在流量进来之前 , 超过的流量进行限制 。
熔断是一种应对故障的机制 , 发生在流量进来之后 , 如果系统发生故障或者异常 , 熔断会自动切断请求 , 防止故障进一步扩展 , 导致服务雪崩 。
限流和削峰有什么区别?削峰是对流量的平滑处理 , 通过缓慢地增加请求的处理速率来避免系统瞬时过载 。
削峰大概就是水库 , 把流量储存起来 , 慢慢流 , 限流大概就是闸口 , 拒绝超出的流量 。
限流的通用流程那么具体限流怎么实现呢?可以概括为以下几个步骤:

四种分布式限流算法实现!

文章插图
限流通用流程
  1. 统计请求流量:记录请求的数量或速率 , 可以通过计数器、滑动窗口等方式进行统计 。
  2. 判断是否超过限制:根据设定的限制条件 , 判断当前请求流量是否超过限制 。
  3. 执行限流策略:如果请求流量超过限制 , 执行限流策略 , 如拒绝请求、延迟处理、返回错误信息等 。
  4. 更新统计信息:根据请求的处理结果 , 更新统计信息 , 如增加计数器的值、更新滑动窗口的数据等 。
  5. 重复执行以上步骤:不断地统计请求流量、判断是否超过限制、执行限流策略、更新统计信息
需要注意的是 , 具体的限流算法实现可能会根据不同的场景和需求进行调整和优化 , 比如使用令牌桶算法、漏桶算法等 。
单机限流和分布式限流我们注意到 , 在限流的通用流程里 , 需要统计请求量、更新统计量 , 那么这个请求量的统计和更新就必须维护在一个存储里 。
假如只是一个单机版的环境 , 那就很好办了 , 直接储存到本地 。
四种分布式限流算法实现!

文章插图
单机vs集群
但是一般来讲 , 我们的服务都是集群部署的 , 如何来实现多台机器之间整体的限流呢?
这时候就可以把我们的统计信息放到TAIr或redis等分布式的K-V存储中 。
四种限流算法与分布式实现接下来 , 我们开始实现一些常见的限流算法 , 这里使用Redis作为分布式存储 , Redis不用多说了吧 , 最流行的分布式缓存DB;Redission作为Redis客户端 , Redission单纯只是用来做分布式锁 , 有些”屈才“ , 其实用来作为Redis的客户端也非常好用 。
五种限流算法分布式实现
在开始之前 , 我们先简单准备一下环境 , Redis安装和项目创建就不多说了 。
  • 添加依赖
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.16.2</version></dependency>
  • 用单例模式获取RedissonClient , 这里就不注册成bean了 , 跑单测太慢
 public class RedissonConfig {private static final String REDIS_ADDRESS = "redis://127.0.0.1:6379";private static volatileRedissonClient redissonClient;public static RedissonClient getInstance(){if (redissnotallow==null){synchronized (RedissonConfig.class){if (redissnotallow==null){Config config = new Config();config.useSingleServer().setAddress(REDIS_ADDRESS);redissonClient = Redisson.create(config);return redissonClient;}}}return redissonClient;}}


推荐阅读