惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
AI
AI
SecWiki News
SecWiki News
宝玉的分享
宝玉的分享
Scott Helme
Scott Helme
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Engineering at Meta
Engineering at Meta
博客园 - 叶小钗
The GitHub Blog
The GitHub Blog
Microsoft Azure Blog
Microsoft Azure Blog
N
News and Events Feed by Topic
Cloudbric
Cloudbric
B
Blog
Cisco Talos Blog
Cisco Talos Blog
V
Vulnerabilities – Threatpost
N
News and Events Feed by Topic
V
Visual Studio Blog
A
Arctic Wolf
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
U
Unit 42
S
Security @ Cisco Blogs
博客园 - 聂微东
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Apple Machine Learning Research
Apple Machine Learning Research
Y
Y Combinator Blog
G
GRAHAM CLULEY
L
LINUX DO - 热门话题
量子位
NISL@THU
NISL@THU
Webroot Blog
Webroot Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Troy Hunt's Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Tenable Blog
月光博客
月光博客
S
Security Affairs
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
The Hacker News
The Hacker News
Spread Privacy
Spread Privacy
D
Docker
www.infosecurity-magazine.com
www.infosecurity-magazine.com
雷峰网
雷峰网
博客园 - 司徒正美
T
The Exploit Database - CXSecurity.com
Hugging Face - Blog
Hugging Face - Blog
Help Net Security
Help Net Security
D
DataBreaches.Net

咸糖 - 自律者自由

2025 年终总结:降噪、重构与长期主义 在新加坡和新山吃过最好的食物(持续更新) 写给还在迷茫的你:我的三本大学回忆 2024 年终总结 Neovim: No Crash Incremental Selection 2022 年终总结 使用 neovim 作为 PDE(个性化开发环境) shell 是一个不错的生产力工具 使用二八法则省力地学习 awk 肉身翻墙新加坡安顿指南 使用 Docker Compose 建立你自己的开发环境 关于编写可维护的代码的一些实践与想法 我为什么使用双向链接做笔记? 关于焦虑和拖延症 Golang: 如何处理日渐膨胀的 interface 使用番茄工作法来更好的利用你的时间 Unix 如何杀死一个进程和它的子孙进程? Golang: 让你的零值更有用 使用 Mock 和 Interface 进行 Golang 单测 关于 Golang Slice 的一些细节 总结一些计算机常用的原则 重新学习英语语法 上班族近期小半年入门投资基金组合的学习与实践经历 疫情期间的肉身翻墙新加坡指南 About me 软技能:大厂底层员工打工指南 软技能:我是如何获取知识与信息的? 实现一个AtomicInteger GC root 在哪里? 什么是 Minor GC/Major GC 漏桶算法的设计与实现 剑指offer 单例模式 TCP 针对面试学习 Actor 如何处理阻塞消息 Akka 源码解析 How to learn scala AES 需要限制 SEED 长度 Java 如何区分==与.equals()方法 2018年年度总结 Java 集合扩容
分布式的令牌桶算法的实现
xiantang · 2020-04-09 · via 咸糖 - 自律者自由

文章目录

【注意】最后更新于 April 9, 2020,文中内容可能已过时,请谨慎使用。

什么是令牌桶算法?

令牌桶算法是一种限流算法,他与漏桶算法的实现是一种相反的实现。

漏桶算法是按照一定频率的速率进行漏水,然后对于我们的请求就可以想象成上边的水龙头。

img

令牌桶算法则是定时的往桶中放入令牌,然后每次请求都会从令牌桶中获取一个令牌,如果桶中没有令牌,则拒绝请求或者阻塞直到令牌可以获得。

img

分布式的令牌桶算法

因为看到的令牌桶算法都是单机的,举个例子: RateLimiter 他就是一个线程级别的令牌桶算法。

因为需要实现一个分布式的令牌桶算法,所以我这边使用的是一个 Redis 作为令牌桶的容器。

然后我们来看看主要的令牌桶算法的思路:

其实他并没有创建一个线程不断的往令牌桶里边放数据,他采用的懒计算的方式进行处理,这样的好处是性能消耗比较小,可以避免一些无用的轮训操作。

其实我们可以吧令牌桶想象为一个对象:

1
2
3
4
5
6
7
case class RedisPermits(
                    name:String,
                    maxPermits: Long,
                    storePermits: Long,
                    intervalMillis: Long,
                    nextFreeTicketMillis: Long
                  ) {}

我来介绍一下这个令牌桶的成员变量:

Name: 表示这个令牌桶的名称,也就是存在redis中的key。

maxPermits: 表示令牌桶中令牌的数目。

storePermits: 表示令牌桶中当前令牌的数目。

intervalMillis: 每次放入令牌之间的间隔时间。根据请求的 QPS 求出。

nextFreeTicketMillis: 下一次能获取这些令牌的时间。

对于一个获取令牌的操作,我们可以判断为是否能够获取到令牌,也就是 nextFreeTicketMillis 是在当前时间之前还是之后。

nextFreeTicketMillis 在当前时间之前

image-20200409154830414

通过图中的公式可以计算出当前存储的令牌数目。和你需要的令牌数目相互比较:

  • 如果够用就减去需要使用的令牌数目,将 nextFreeTicketMillis 设置为 now。立马返回函数就行啦。
  • 如果不够用就得到当前的令牌数目,将当前令牌数目设置为0,然后求出需要生成的数目,将 nextFreeTicketMillis 向后推,生成的时间。当前线程等待对应 nextFreeTicketMillis - now 的时间就能求出需要等待的时间。进行睡眠,睡眠结束就可以做相应的请求了。

nextFreeTicketMillis 在当前时间之后

image-20200409155633013

nextFreeTicketMillis 因为在当前时间之后所以当前令牌桶肯定是没有数据的,所以我们需要将睡眠的时间往后拖就好了,就是 nextFreeTicketMillis =+ intervalMillis*need 然后当前线程睡眠 nextFreeTicketMillis - now 的时间就行啦。

优点

令牌桶算法可以采用将 maxPermits 也就是最大令牌数量设置为 1 方式,将请求打均匀,非常适合需要匀速调用的场景。

并且使用本实现可以将请求阻塞起来,保证请求能够都打到,其实也是一个削峰的作用。

文章作者 xiantang

上次更新 2020-04-09

赞赏支持

微信打赏 支付宝打赏