令牌桶和漏桶算法的区别

2024-05-09 17:36
文章标签 算法 区别 令牌 漏桶

本文主要是介绍令牌桶和漏桶算法的区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

令牌桶和漏桶算法的区别

  • 概述
  • 结论
  • 详细
    • 令牌桶代码实现
    • 漏桶算法代码实现

概述

令牌桶算法和漏桶算法常用作限流器。从使用的角度,而不是算法实现的角度,两种算法其实只向我们暴露一个方法IsLimit,无入参,出参是布尔类型,代表是否限流。

令牌桶算法:有一个固定容量的桶,以恒定速率向桶里面添加令牌,我们可以从桶里面每次取出一个令牌。当取的很频繁时,就可能桶中没有令牌可取,此时被限流。

漏桶算法:有一个固定容量的桶,里面装了水,桶底部有洞,水以恒定速率向外流出,我们可以向桶里加水。当加水动作很频繁时,超过流出速度,桶里的水会满,此时被限流。

可以结合后面的代码来理解两种算法

结论

作为限流器,从使用方面,令牌桶和漏桶算法没有区别,两者均需要初始化桶容量和速率,都会以固定速率往桶里加令牌或漏水。
实现原理方面:

  • 令牌桶算法中,如果从桶中拿不到令牌,即桶空了,被限流
  • 漏桶算法中,如果桶满,则被限流

两者唯一的区别,在于使用方面。漏桶算法可以实现为一个带容量的消息队列,分别有生产者和消费者,生产者向桶中加水,消费者从桶中取水(漏水),由于消费者以固定速率取水,所以有“流量整形”的味道。在这种场景,水有了特殊的含义,不仅仅是一个计数器。且有独特的消费者。
令牌桶算法中的令牌数量,一般仅作为简单的计数器。

详细

对于令牌桶算法以固定速率生成令牌,或者是漏桶算法以固定速率漏水,具体实现,一方面可以通过独立线程去做“加令牌”或“漏水”操作,另一方面可以“惰性”操作,即记录上一次操作的时间,仅当取令牌或添水时,才计算这个时间段本应该“生成多少令牌”或“漏多少水”。

令牌桶代码实现

package mainimport ("fmt""time"
)type TokenBucket struct {capacity  inttokens    intrate      intlastToken time.Time
}func NewTokenBucket(capacity, rate int) *TokenBucket {return &TokenBucket{capacity:  capacity,tokens:    capacity,rate:      rate,lastToken: time.Now(),}
}func (tb *TokenBucket) AllowRequest() bool {now := time.Now()tb.tokens += int(now.Sub(tb.lastToken).Seconds()) * tb.rateif tb.tokens > tb.capacity {tb.tokens = tb.capacity}tb.lastToken = nowif tb.tokens > 0 {tb.tokens--return true}return false
}func main() {tb := NewTokenBucket(10, 1)for i := 0; i < 15; i++ {if tb.AllowRequest() {fmt.Println("Request", i, "allowed")} else {fmt.Println("Request", i, "blocked")}time.Sleep(time.Second)}
}

漏桶算法代码实现

package mainimport ("fmt""time"
)type LeakyBucket struct {capacity  intwater     intrate      intlastLeak  time.Time
}func NewLeakyBucket(capacity, rate int) *LeakyBucket {return &LeakyBucket{capacity: capacity,water:    0,rate:     rate,lastLeak: time.Now(),}
}func (lb *LeakyBucket) AllowRequest() bool {now := time.Now()elapsed := int(now.Sub(lb.lastLeak).Seconds())lb.water -= elapsed * lb.rateif lb.water < 0 {lb.water = 0}lb.lastLeak = nowif lb.water < lb.capacity {lb.water++return true}return false
}func main() {lb := NewLeakyBucket(10, 1)for i := 0; i < 15; i++ {if lb.AllowRequest() {fmt.Println("Request", i, "allowed")} else {fmt.Println("Request", i, "blocked")}time.Sleep(time.Second)}
}

这篇关于令牌桶和漏桶算法的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/974048

相关文章

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

分辨率三兄弟LPI、DPI 和 PPI有什么区别? 搞清分辨率的那些事儿

《分辨率三兄弟LPI、DPI和PPI有什么区别?搞清分辨率的那些事儿》分辨率这个东西,真的是让人又爱又恨,为了搞清楚它,我可是翻阅了不少资料,最后发现“小7的背包”的解释最让我茅塞顿开,于是,我... 在谈到分辨率时,我们经常会遇到三个相似的缩写:PPI、DPI 和 LPI。虽然它们看起来差不多,但实际应用

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

GORM中Model和Table的区别及使用

《GORM中Model和Table的区别及使用》Model和Table是两种与数据库表交互的核心方法,但它们的用途和行为存在著差异,本文主要介绍了GORM中Model和Table的区别及使用,具有一... 目录1. Model 的作用与特点1.1 核心用途1.2 行为特点1.3 示例China编程代码2. Tab

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

Nginx指令add_header和proxy_set_header的区别及说明

《Nginx指令add_header和proxy_set_header的区别及说明》:本文主要介绍Nginx指令add_header和proxy_set_header的区别及说明,具有很好的参考价... 目录Nginx指令add_header和proxy_set_header区别如何理解反向代理?proxy

Java中&和&&以及|和||的区别、应用场景和代码示例

《Java中&和&&以及|和||的区别、应用场景和代码示例》:本文主要介绍Java中的逻辑运算符&、&&、|和||的区别,包括它们在布尔和整数类型上的应用,文中通过代码介绍的非常详细,需要的朋友可... 目录前言1. & 和 &&代码示例2. | 和 ||代码示例3. 为什么要使用 & 和 | 而不是总是使

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

Spring中@RestController和@Controller的使用及区别

《Spring中@RestController和@Controller的使用及区别》:本文主要介绍Spring中@RestController和@Controller的使用及区别,具有很好的参考价... 目录Spring中@RestController和@Controller使用及区别1. 基本定义2. 使

Qt 中 isHidden 和 isVisible 的区别与使用小结

《Qt中isHidden和isVisible的区别与使用小结》Qt中的isHidden()和isVisible()方法都用于查询组件显示或隐藏状态,然而,它们有很大的区别,了解它们对于正确操... 目录1. 基础概念2. 区别清见3. 实际案例4. 注意事项5. 总结1. 基础概念Qt 中的 isHidd