令牌桶限流-java实现
令牌桶的容量是c(个),令牌以速度r(个/秒)均匀的放入桐中,上个请求的时间为at(时间戳),上个请求后剩余的令牌数目为w(个),现在有个请求b对象进来了,现在请求的时间bt=now(),伪代码如上图,其中wb代表从at到bt时间段内产生的令牌数,产生的令牌数加上上次剩余的令牌数是不能大于桶容量的
Java实现代码:
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;public class BucketLimiter {/* 桶容量 */private final long c;/* 令牌放入速度 */private final int r;/* 桶初始化时间 */private final long initTime;/* 模拟redis缓存 */private final Map<String, Object> redisCache = new HashMap<>(2048);/* 请求时间redis key */public static final String REQUEST_TIME = "REQUEST_TIME";/* 请求后剩余令牌数redis key */public static final String TOKEN_REMAINS = "TOKEN_REMAINS";/*** @param c 桶容量* @param r 令牌放入速度*/public BucketLimiter(long c, int r) {this.c = c;this.r = r;this.initTime = System.currentTimeMillis();}/* 注意这里要加同步 */public synchronized boolean permit() {//获取上个请求后令牌桶状态BucketStatus status = getLastRequestBucketStatus();//上个请求时间final long at = status.getRequestTime();//上个请求后剩余令牌数long w = status.getRemains();//现请求时间final long bt = System.currentTimeMillis();//从上个请求到现在请求增加的令牌数final long wb = (bt - at)/1000 * r;System.out.println("===生产数:"+wb);//现在桶里面剩余的令牌数w = Math.min(w + wb, c);//假设每次消耗一个令牌if (w > 0) {w--;//请求时间和剩余令牌数redisCache.put(REQUEST_TIME, bt);redisCache.put(TOKEN_REMAINS, w);return true;} else {return false;}}/*** @description 获取上个请求后令牌桶状态* @author yulin.chen* @date 2021/10/26 10:27*/private BucketStatus getLastRequestBucketStatus() {Object requestTime = redisCache.get(REQUEST_TIME);Object remains = redisCache.get(TOKEN_REMAINS);if (null == requestTime) {//请求时间为空就是第一次请求,剩余数设置为0,时间设置为初始化时间return new BucketStatus(0L, this.initTime);}return new BucketStatus(Long.parseLong(String.valueOf(remains)), Long.parseLong(String.valueOf(requestTime)));}/****/public static class BucketStatus {/* 剩余令牌数 */private final Long remains;/* 请求时间 */private final Long requestTime;public BucketStatus(Long remains, Long requestTime) {this.remains = remains;this.requestTime = requestTime;}public Long getRemains() {return remains;}public Long getRequestTime() {return requestTime;}}
}
测试代码
public static void main(String[] args) throws InterruptedException {BucketLimiter limiter = new BucketLimiter(5000, 5);//生产5秒,每秒生产5个TimeUnit.SECONDS.sleep(5);for (int i = 0; i < 10000; i++) {new Thread(() -> System.out.println(Thread.currentThread().getName() + " request permit:" + limiter.permit()), "[Thread " + i + "]").start();}
}
令牌桶限流-java实现相关推荐
- Jedis使用lua脚本完成令牌桶限流
Jedis使用lua脚本完成令牌桶限流 文章目录 Jedis使用lua脚本完成令牌桶限流 一.lua脚本的简单语法 二.令牌桶限流 1. 构思 2. 实现 三.Jemeter压测工具测试 一.lua脚 ...
- 可能要用心学高并发核心编程,限流原理与实战,分布式令牌桶限流
实战:分布式令牌桶限流 本节介绍的分布式令牌桶限流通过Lua+Java结合完成,首先在Lua脚本中完成限流的计算,然后在Java代码中进行组织和调用. 分布式令牌桶限流Lua脚本 分布式令牌桶限流Lu ...
- 【秒杀系统】零基础上手秒杀系统(二):令牌桶限流 + 再谈超卖
前言 本文是秒杀系统的第二篇,通过实际代码讲解,帮助你快速的了解秒杀系统的关键点,上手实际项目. 本篇主要讲解接口限流措施,接口限流其实定义也非常广,接口限流本身也是系统安全防护的一种措施,暂时列举这 ...
- ASP.NET Core中使用令牌桶限流
在限流时一般会限制每秒或每分钟的请求数,简单点一般会采用计数器算法,这种算法实现相对简单,也很高效,但是无法应对瞬时的突发流量. 比如限流每秒100次请求,绝大多数的时间里都不会超过这个数,但是偶尔某 ...
- 什么是限流?为什么会限流呢?常见的限流算法【固定窗口限流、滑动窗口限流、漏桶限流、令牌桶限流】是什么呢?
什么是限流?为什么会限流呢?常见的限流算法[固定窗口限流.滑动窗口限流.漏桶限流.令牌桶限流]是什么呢? 什么是限流? 为什么会限流? 1. 固定窗口限流算法 1.1 什么是固定窗口限流算法 1.2 ...
- rateLimiter令牌桶限流算法
RateLimiter是guava提供的基于令牌桶算法的实现类,可以非常简单的完成限流特技,并且根据系统的实际情况来调整生成token的速率. 通常可应用于抢购限流防止冲垮系统:限制某接口.服务单位时 ...
- 基于Redis和 Lua 实现分布式令牌桶限流
rpc-tech-stack 系列的实践文章 ~ 本文属于限流话题. 限流是一个很大的话题,准备把其中的所有限流器都实现一遍,以此也算全都写过了,到时候再用也不至于会心虚,毕竟真实写完成过.本文主要讲 ...
- 分布式限流实战--redis实现令牌桶限流
这篇文章我们主要是分析一下分布式限流的玩法. 因为限流也是一个经典用法了. 1.微服务限流 随着微服务的流行,服务和服务之间的稳定性变得越来越重要.缓存.降级和限流是保护微服务系统运行稳定性的三大利器 ...
- 令牌桶限流之redis-cell的安装,使用,详解
简言 1. redis使用有序集合zset也能实现简单的限流,但是只能处理几十,几百的量级,因为zset需要记录每一条信息,很占据空间.要想处理更大数量级的限流,必须使用其他方法 2. 通常的限流算法 ...
- 十三水算法php_基于PHP+Redis令牌桶限流
一 .场景描述 在开发接口服务器的过程中,为了防止客户端对于接口的滥用,保护服务器的资源, 通常来说我们会对于服务器上的各种接口进行调用次数的限制.比如对于某个 用户,他在一个时间段(interval ...
最新文章
- Prokka:快速原核基因组、宏基因组基因注释
- 2021金蝶全球创见者大会成功举办, 500强企业共话EBC数字战斗力
- java有string这个类型吗_关于java的String类型
- mysql undrop_MySQL 如何对InnoDB使用Undrop来恢复InnoDB数据
- lda数学八卦_【技术博客】文本挖掘之LDA主题模型
- Less的Mixin嵌套规则
- UFLDL教程 -- 译文版
- idea2020 个性化设置
- IM 即时通讯实现原理
- Keil 5 C51与STM32
- 树莓派 | RSSHub+TTRSS
- 实验楼Linux入门:Linux用户管理
- 通过Excel表格批量生成汉信码
- 微信公众平台服务器配置时token验证失败
- 亚马逊抄作业,股票打折安排上
- MySQL_启动_Windows
- python爬虫 豆瓣电影
- 惠鑫云安全稳定为什么说澳元是高息钱银?高息钱银有哪些
- vue 视频播放插件vue-video-player的使用
- CSS餐厅小游戏练习1~32关(附答案和链接)