这篇文章我们主要是分析一下分布式限流的玩法。 因为限流也是一个经典用法了。

1.微服务限流

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。缓存、降级和限流是保护微服务系统运行稳定性的三大利器。

缓存的目的是提升系统访问速度和增大系统能处理的容量,而降级是当服务出问题或者影响到核心流程的性能则需要暂时屏蔽掉,待高峰或者问题解决后再打开,而有些场景并不能用缓存和降级来解决,比如稀缺资源、数据库的写操作、频繁的复杂查询,因此需有一种手段来限制这些场景的请求量,即限流。

比如当我们设计了一个函数,准备上线,这时候这个函数会消耗一些资源,处理上限是1秒服务3000个QPS,但如果实际情况遇到高于3000的QPS该如何解决呢?

所以限流的目的应当是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统,一旦达到限制速率就可以拒绝服务、等待、降级。

学习如何去实现一个分布式限流框架,首先,我们需要去了解最基本的两种限流算法。

2.限流算法

2.1漏桶算法

漏桶算法思路很简单,水(也就是请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会直接溢出,然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率。示意图(来源网络)如下:

微服务架构下的分布式限流方案全解析

2.2令牌桶算法

令牌桶算法和漏桶算法效果一样但方向相反的算法,更加容易理解。随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS=100,则间隔是10ms)往桶里加入令牌(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了。新请求来临时,会各自拿走一个令牌,如果没有令牌可拿了就阻塞或者拒绝服务。示意图(来源网络)如下:

微服务架构下的分布式限流方案全解析

2.3算法选择

漏桶算法与令牌桶算法的区别在于,漏桶算法能够强行限制数据的传输速率,令牌桶算法能够在限制数据的平均传输速率的同时还允许某种程度的突发情况。令牌桶还有一个好处是可以方便的改变速度。一旦需要提高速率,则按需提高放入桶中的令牌的速率。所以,限流框架的核心算法还是以令牌桶算法为主。

3.本地限流

已知上面讲述的令牌桶算法的原理,如何通过代码实现?

本地限流的实现可以用Long长整型作为令牌桶,为了达到无锁,建议使用Long的原子类型AtomicLong,使用AtomicLong的好处就是可以非常方便的对其进行CAS加操作与CAS减操作(也就是令牌桶令牌的放入与拿取),以避免线程的上下文切换的开销,核心CAS算法如下:

private boolean tryAcquireFailed() {long l = bucket.longValue();while (l > 0) {if (bucket.compareAndSet(l, l - 1)) {return true;}l = bucket.longValue();}return false;
}

根据上述了解的令牌桶算法可以得知,令牌桶需要一个ScheduledThread不断的放入令牌,这部分的代码如下:

ScheduledThreadExecutor.scheduleAtFixedRate(() -> bucket.set(rule.getLimit()), rule.getInitialDelay(), rule.getPeriod(), rule.getUnit()
);

4.分布式限流概述

分布式限流需要解决什么问题呢?我想至少有下面几个:

1.动态规则:比如限流的QPS我们希望可以动态修改,限流的功能可以随时开启、关闭,限流的规则可以跟随业务进行动态变更等。

2.集群限流:比如对Spring Cloud微服务架构中的某服务下的所有实例进行统一限流,以控制后续访问数据库的流量。

3.熔断降级:比如在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。

可选的其它几个功能,诸如实时监控数据、网关流控、热点参数限流、系统自适应限流、黑白名单控制、注解支持等,这些功能其实可以非常方便的进行扩展。

以上的内容来源于 分布式限流概念 ,大家可以查看。

分布式限流实操–令牌桶算法限流

这里就直接帖一下代码就好了


/*** 令牌桶算法限流* @author 田培融*/
@Slf4j
@Component
public class RedisRaterLimiter {@Autowiredprivate StringRedisTemplate redisTemplate;public String acquireToken(String point, Integer limit, Long timeout) {String maxCountKey = "BUCKET:MAX_COUNT:" + point;String currCountKey = "BUCKET:CURR_COUNT:" + point;try {// 令牌值String token = "T";// 无效的限流值 返回tokenif(limit<=0||timeout<=0){return token;}// maxCount为主要判断标志String maxCount = redisTemplate.opsForValue().get(maxCountKey);String currCount = redisTemplate.opsForValue().get(currCountKey);// 初始if(StrUtil.isBlank(maxCount)){// 初始计数为1redisTemplate.opsForValue().set(currCountKey, "1", timeout, TimeUnit.MILLISECONDS);// 总数redisTemplate.opsForValue().set(maxCountKey, limit.toString(), timeout, TimeUnit.MILLISECONDS);return token;} else if (StrUtil.isNotBlank(maxCount)&&StrUtil.isNotBlank(currCount)){// 判断是否超过限制if(Integer.valueOf(currCount)<Integer.valueOf(maxCount)){// 计数加1redisTemplate.opsForValue().set(currCountKey, String.valueOf(Integer.valueOf(currCount)+1), timeout, TimeUnit.MILLISECONDS);return token;}} else {// currCount变量先失效(几乎不可能) 返回tokenreturn token;}} catch (Exception e) {log.error("限流出错,请检查Redis运行状态\n"+e.toString());}return null;}
}

第一个参数只要不重复就行,随便写。 主要是为了区别要限制什么。 第二个参数是表示限制访问的次数。第三个参数是表示多长时间内限制访问的次数。

使用案例:

 String token = redisRaterLimiter.acquireToken("upload:"+ipInfoUtil.getIpAddr(request), 1, 300000L);if (StrUtil.isBlank(token)) {throw new LimitException("上传那么多干嘛,等等再传吧");}

好了,这就是我们项目中的分布式限流了。

猿来衣舍

这是博主开的淘宝小店,主要经营舒适保暖的服饰,有袜子、主题卫衣、保暖衣。欢迎大家选购。

TEngine java开发脚手架

测试账号 test 123456

我这个脚手架目前是做为店铺福利送给顾客的,联系客户获取

猿来衣舍
猿来衣舍
猿来衣舍
猿来衣舍

打开淘宝搜索 “猿来衣舍”这四个字就可以搜到小店,希望大家多多支持。

一个人能够走多远,关键在于与谁同行,我用跨越山海的一路相伴,希望得到您用金钱的称赞。

分布式限流实战--redis实现令牌桶限流相关推荐

  1. 可能要用心学高并发核心编程,限流原理与实战,分布式令牌桶限流

    实战:分布式令牌桶限流 本节介绍的分布式令牌桶限流通过Lua+Java结合完成,首先在Lua脚本中完成限流的计算,然后在Java代码中进行组织和调用. 分布式令牌桶限流Lua脚本 分布式令牌桶限流Lu ...

  2. ASP.NET Core中使用令牌桶限流

    在限流时一般会限制每秒或每分钟的请求数,简单点一般会采用计数器算法,这种算法实现相对简单,也很高效,但是无法应对瞬时的突发流量. 比如限流每秒100次请求,绝大多数的时间里都不会超过这个数,但是偶尔某 ...

  3. Jedis使用lua脚本完成令牌桶限流

    Jedis使用lua脚本完成令牌桶限流 文章目录 Jedis使用lua脚本完成令牌桶限流 一.lua脚本的简单语法 二.令牌桶限流 1. 构思 2. 实现 三.Jemeter压测工具测试 一.lua脚 ...

  4. 【秒杀系统】零基础上手秒杀系统(二):令牌桶限流 + 再谈超卖

    前言 本文是秒杀系统的第二篇,通过实际代码讲解,帮助你快速的了解秒杀系统的关键点,上手实际项目. 本篇主要讲解接口限流措施,接口限流其实定义也非常广,接口限流本身也是系统安全防护的一种措施,暂时列举这 ...

  5. 什么是限流?为什么会限流呢?常见的限流算法【固定窗口限流、滑动窗口限流、漏桶限流、令牌桶限流】是什么呢?

    什么是限流?为什么会限流呢?常见的限流算法[固定窗口限流.滑动窗口限流.漏桶限流.令牌桶限流]是什么呢? 什么是限流? 为什么会限流? 1. 固定窗口限流算法 1.1 什么是固定窗口限流算法 1.2 ...

  6. redis实现令牌桶的正确姿势

    redis实现令牌桶的正确姿势 场景描述 解决方案 最近需要自己做一个限流功能,其他业务代码都好说.唯一的终点就是限流实现,想到redis可以实现令牌桶.一拍脑门,就用它了! 场景描述 真实开发中才发 ...

  7. 基于Redis和 Lua 实现分布式令牌桶限流

    rpc-tech-stack 系列的实践文章 ~ 本文属于限流话题. 限流是一个很大的话题,准备把其中的所有限流器都实现一遍,以此也算全都写过了,到时候再用也不至于会心虚,毕竟真实写完成过.本文主要讲 ...

  8. 十三水算法php_基于PHP+Redis令牌桶限流

    一 .场景描述 在开发接口服务器的过程中,为了防止客户端对于接口的滥用,保护服务器的资源, 通常来说我们会对于服务器上的各种接口进行调用次数的限制.比如对于某个 用户,他在一个时间段(interval ...

  9. php限制接口访问次数_令牌桶限流思路分享(PHP+Redis实现机制)

    一 .场景描述 在开发接口服务器的过程中,为了防止客户端对于接口的滥用,保护服务器的资源, 通常来说我们会对于服务器上的各种接口进行调用次数的限制.比如对于某个 用户,他在一个时间段(interval ...

最新文章

  1. 利用UltraScale和UltraScale+FPGA和MPSOC加速DSP设计生产力
  2. 用matlab自己搭建bp神经网络,怎样在matlab里建立一个BP神经网络模型?
  3. view里文书删除时报错的解决案
  4. flutter中本地存储shared_preferences的使用
  5. GPU(CUDA)学习日记(十三)------ CUDA内存简介
  6. 优先队列/单调队列 - 滑动窗口最大值
  7. 记tcp网络编程中遇到的readline()方法
  8. ctfmon.exe windows输入法无法启动
  9. 傲梅分区助手克隆Linux硬盘,傲梅分区助手复制磁盘或克隆磁盘到另外磁盘
  10. JAVA - Quartz 定时任务_启动原理
  11. 【Java 8 新特性】使用Collectors.toList()方法将Map转化成List的示例
  12. 06 第五章 一阶逻辑等值演算与推理
  13. 4芯网线接法(电话线接网线水晶头)
  14. mocha测试框架使用
  15. 网络聊天中的英语简写
  16. 06_2_Pytorch的基础数据类型、CPU tensor类型和GPU tensor类型、判断数据类型、CPU或GPU张量之间的转换、数据类型转换、1-4维向量、Tensor张量、Variable等
  17. Ubuntu 16.04卸载LibreOffice等不常用软件
  18. windows系统镜像里的×64和×86有什么区别?
  19. WEB-4-JavaScript(JS)
  20. 《遗传算法原理及应用》笔记—进化计算

热门文章

  1. 树莓派Pico W无线WiFi开发板使用方法及MicroPython网络编程实践
  2. 2021年门座式起重机司机报名考试及门座式起重机司机考试技巧
  3. python logging模块打印log日志到文件和屏幕
  4. 共享充电宝行业面临狼来了,新进入者疑似滥用垄断权力
  5. 32位PowerPC常用指令集总结
  6. 2021-2027全球与中国家畜口蹄疫 (FMD) 疫苗市场现状及未来发展趋势
  7. [wp7软件]相机 画图 截屏 photo 集合 软件(三)
  8. 基于JAVA漫画网站系统计算机毕业设计源码+数据库+lw文档+系统+部署
  9. pjax php,ThinkPHP5.1配合pjax实现菜单栏无刷新跳转
  10. Adapter类型控件之Spinner(列表选项框)