电商系统中的秒杀高并发单机限流实战

今天,抽空,我给大家介绍一下限流。目前关于限流的框架和工具都比较多,比如 Redis、阿里的 Sentinel、Nginx、OpenResty 等。今天我先给大家介绍一个简单的限流,单机限流方法。
限流不管是在生活中还是代码中都很常用,比如上图中的某景区黄金周限流。
限流,顾名思义就是在规定的时间内限制流通量。在项目代码中就是限制单位时间内请求的并发数,确保服务的可靠性。一般限流、缓存、降级是处理高并发的常见 3 种手段,也是程序员必知必会的必备生存技能。
限流的使用场景太多了,多的数不过来。比如:秒杀限流,导出报表限流等。如果按资源分类,限制 MQ 消费、CPU、内存、磁盘使用率、网络连接数、网络流量等。而我们今天要讲的是,限制接口的并发调用数。
限流基本上有两个主要且非常经典的算法:漏桶算法和令牌桶算法。
漏桶算法就像一个漏斗一样,进来的水量就好像访问流量一样,而出去的水量就像是我们的系统处理请求一样。当访问流量过大时,这个漏斗中就会积水,如果水太多了就会溢出,直接响应超时或者系统繁忙等情况。
漏桶算法的实现往往依赖于队列,请求到达时,如果队列未满则直接放入队列,如果满了则溢出。然后有一个处理器按照固定频率从队列头取出请求进行处理。
根据生活中的现象以及上图中描述的出水速率恒定。因此漏桶算法的一个重要特征或缺点是,它的输出速率是恒定的,这也是区别于令牌桶的根本。
令牌桶算法则是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌。桶中存放的令牌数有最大上限,超出之后就被丢弃或者拒绝。当流量或者网络请求到达时,每个请求都要获取一个令牌,如果能够获取到,则直接处理,并且令牌桶删除一个令牌。如果获取不到,该请求就要被限流,要么直接丢弃,要么在缓冲区等待。
令牌桶算法和漏桶算法的主要区别如下:
  • 漏桶是出,令牌是进
  • 令牌是允许伸缩的
漏桶算法不能够有效地使用网络资源,因为漏桶的漏出速率是固定的,所以即使网络中没有发生拥塞,漏桶算法也不能使某一个单独的数据流达到端口速率。因此,漏桶算法对于存在突发特性的流量来说缺乏效率。而令牌桶算法则能够满足这些具有突发特性的流量。通常,漏桶算法与令牌桶算法结合起来为网络流量提供更高效的控制。
这两个算法的具体实现,我就不列举代码了。我们今天直接来使用 Guava 这个开眼框架来实现限流,这是一个很好的工具类框架,如果你把它的源码完整的看一遍,我相信你的技能会有很大的提升。
Guava 的 RateLimiter 实现令牌桶算法:SmoothBursty 实现了平滑突发限流、SmoothWarmingUp 实现了平滑预热限流。
RateLimiter 采用工厂方法模式,根据调用参数的不同,生成 两个不同的 RateLimiter 子类:SmoothBursty 和 SmoothWarmingUp。
RateLimiter 类是一个线程安全的类,大家可以放心的使用。下面看一下我的单机脱敏后的秒杀简化代码。
SmoothWarmingUp 创建方式要使用这个函数:RateLimiter.create(doublepermitsPerSecond, long warmupPeriod, TimeUnit unit)。其中 permitsPerSecond 参数表示每秒新增的令牌数,warmupPeriod 参数表示在从冷启动速率过渡到平均速率的时间间隔。
SmoothWarmingUp 的速率是梯形上升速率的,也就是说冷启动时会以一个比较大的速率慢慢到平均速率;然后趋于平均速率(梯形下降到平均速率)。可以通过调节 warmupPeriod 参数实现一开始就是平滑固定速率。
上面我介绍的方法都是单机限流,或者说是应用级别的限流,现在假设将应用部署到多台机器,应用级限流方式只是单应用内的请求限流,不能进行全局限流。因此我们需要分布式限流和接入层限流来解决这个问题。
分布式限流,一般需要借助第三方系统来实现。比如:Redis、Sentinel。也或者 Nginx、OpenResty 等再集群入口处进行限流,这部分后面我抽出时间再写文章来扩展吧。
本站所有文章均由网友分享,仅用于参考学习用,请勿直接转载,如有侵权,请联系网站客服删除相关文章。若由于商用引起版权纠纷,一切责任均由使用者承担
极客文库 » 电商系统中的秒杀高并发单机限流实战

Leave a Reply

欢迎加入「极客文库」,成为原创作者从这里开始!

立即加入 了解更多