C++11 Token Bucket (令牌桶)算法的锁无实现及应用

news2025/6/9 8:47:47

Token Bucket(令牌桶)算法是一种在流量控制和资源分配领域被广泛应用的技术。它通过约束数据传输速率或任务执行频率,确保系统在资源有限的情况下,能够稳定、高效地运行,避免因突发流量或任务积压而导致的性能下降甚至系统崩溃。

一、实现原理解析

(一)核心思路

Token Bucket 实现采用锁无设计,依托时间戳与原子操作来实现高效、线程安全的流量控制。其核心在于维护一个虚拟时间点(time_),该时间点标志着下一次能够成功消费特定数量令牌的时刻。系统将当前时间与虚拟时间点进行比较,以此判断消费操作是否可行。

(二)关键成员变量

  • timePerToken_ :这一变量表示生成单个令牌所需的时间间隔。它是基于单位时间(默认设置为 1 秒)与令牌生成速率(rate)计算得出的。例如,当令牌生成速率为每秒 350 个时,生成单个令牌所需的时间则为 1 秒除以 350,大约等于 0.002857 秒。
  • timePerBurst_ :该变量是允许的最大消费量(burstSize)与单个令牌时间的乘积,即计算出一个最大消费周期对应的时间长度。它定义了在何种时间范围内可以消费最大数量的令牌。
  • time_ :这是一个原子变量,用于记录下一次允许消费的虚拟时间点。原子变量的使用确保了在多线程环境下,对时间点的更新和读取操作是线程安全的,避免了因线程竞争而导致的数据不一致问题。

(三)消费逻辑

...
template <typename Clock = std::chrono::steady_clock> class TokenBucket {
public:
  TokenBucket() = default;

  TokenBucket(const uint64_t rate, const uint64_t burstSize)
      : timePerToken_(std::chrono::nanoseconds(std::chrono::seconds(1)) / rate),
        timePerBurst_(burstSize * timePerToken_) {}

  bool consume(const uint64_t tokens) {
    const auto now = Clock::now();
    const auto timeNeeded = tokens * timePerToken_;
    const auto minTime = now - timePerBurst_;
    auto oldTime = time_.load(std::memory_order_relaxed);

    for (;;) {
      auto newTime = oldTime;
      if (minTime > newTime) {
        newTime = minTime;
      }
      newTime += timeNeeded;
      if (newTime > now) {
        return false;
      }
      if (time_.compare_exchange_weak(oldTime, newTime,
                                      std::memory_order_relaxed,
                                      std::memory_order_relaxed)) {
        return true;
      }
    }

    return false;
  }

...
};

If you need the complete source code, please add the WeChat number (c17865354792)

在 consume 函数中,首先获取当前时间(now)。接着,根据请求消费的令牌数量(tokens)乘以单个令牌时间,计算出所需时间(timeNeeded)。随后,确定下一次可能允许消费的最小时间点(minTime),即当前时间减去最大消费周期时间(timePerBurst_),这样可以防止因过度延迟而无法满足最大消费量的要求。

通过循环结合原子变量的 compare_exchange_weak 操作,尝试更新虚拟时间点。如果新的虚拟时间点(newTime)小于等于当前时间,则表明当前有足够的令牌可供消费,此时更新虚拟时间点并返回 true,表示消费成功;反之,若新时间点大于当前时间,则意味着当前没有足够的令牌,消费操作无法完成,返回 false。

二、具体应用场景

(一)网络流量控制

  1. 应用场景描述
    在互联网服务提供商(ISP)的网络设备中,Token Bucket 算法可用于限制用户或特定业务流量的发送速率,防止个别用户或业务过度占用网络带宽,导致网络拥塞,从而保障网络整体的流畅性和稳定性,确保所有用户都能公平地享受网络服务。

  2. 演变图及原理说明

    • 阶段一:无流量控制 :在网络流量较小时,所有数据包都能毫无阻碍地通过网络设备进行传输,用户可以随意发送数据,网络带宽被无限制地使用。此时,网络处于一种自由、无序的状态,容易受到突发大流量的冲击。

    • 阶段二:应用 Token Bucket 算法进行流量控制 :当为用户或业务配置 Token Bucket 后,网络设备开始按照设定的令牌生成速率向令牌桶中添加令牌。每个数据包在发送前都需要从令牌桶中获取相应的令牌。如果令牌桶中有足够的,令牌数据包即可顺利发送,并消耗相应数量的令牌;若令牌不足,数据包则会被缓存或丢弃,等待后续令牌生成后再进行发送。

    • 阶段三:动态调整与稳定控制 :根据网络实际运行情况,如网络拥塞程度、用户需求变化等,网络管理员可以动态调整 Token Bucket 的参数,如令牌生成速率和最大突发量。通过这种方式,网络设备能够灵活地适应不同的流量状况,实现对网络流量的精准控制,维持网络的稳定运行。

  3. 优势体现

    • 保障网络服务质量(QoS) :通过限制流量速率,确保高优先级业务(如语音、视频会议)能够获得足够的带宽,避免因低优先级业务的流量突发而受到影响,从而提高网络的服务质量。
    • 提高网络资源利用率 :合理控制流量,避免网络拥塞导致的大量数据包丢失和重传,使得网络资源能够得到更有效的利用,提升网络整体性能。

(二)API 请求限流

  1. 应用场景描述
    在 Web 服务中,例如电商平台、社交网络平台等,常常需要处理大量来自不同客户端的 API 请求。为了防止某些客户端发送过多请求,导致服务器过载甚至崩溃,影响其他正常用户的访问体验,可以采用 Token Bucket 算法对 API 请求进行限流。
  2. 原理说明
    为每个 API 路径或用户分配一个独立的 Token Bucket。根据业务需求,设置每个 Token Bucket 的令牌生成速率和最大突发量。每当客户端发送一个 API 请求时,系统会尝试从对应的 Token Bucket 中消费一个令牌。如果消费成功,说明当前请求频率在允许范围内,服务器将正常处理该请求;若消费失败,则表明请求过于频繁,服务器将拒绝处理该请求,并返回相应的错误提示信息。
  3. 优势体现
    • 保护服务器免受过载攻击 :有效抵御恶意用户或恶意软件发起的高频请求攻击,如 DDoS 攻击,确保服务器能够在安全、稳定的环境下运行。
    • 公平分配资源 :保证不同客户端能够公平地访问 API 资源,避免个别客户端占用过多的服务器资源,影响其他用户的正常使用。

(三)任务调度与资源分配

  1. 应用场景描述
    在多线程或分布式计算环境中,多个任务需要竞争有限的计算资源(如 CPU、内存、GPU 等)。为了实现任务的有序执行和资源的合理分配,可借助 Token Bucket 算法进行任务调度控制。
  2. 原理说明
    为每类任务或每个任务队列分配一个 Token Bucket。根据任务的优先级和资源需求情况,设置不同的令牌生成速率和最大突发量。当一个任务请求执行时,系统会检查对应的 Token Bucket 中是否有足够的令牌。若有,则允许任务开始执行,并消耗相应数量的令牌;若无,则将任务放入等待队列,等待后续令牌生成后再重新尝试调度执行。
  3. 优势体现
    • 提高资源利用效率 :确保高优先级任务能够及时获取资源并优先执行,避免资源浪费在低价值的任务上,从而提高整个系统的资源利用效率和吞吐量。
    • 灵活适应不同业务需求 :可以根据不同的业务场景和任务特性,灵活调整 Token Bucket 的参数,实现个性化的任务调度策略,满足多样化的业务需求。

三、总结

  1. 高效性 :采用锁无设计,基于时间戳和原子操作实现,避免了传统锁机制带来的线程阻塞与上下文切换开销,极大地提高了系统在高并发场景下的处理性能和响应速度。
  2. 灵活性 :通过简单地调整令牌生成速率和最大突发量这两个关键参数,能够快速适应各种不同的业务场景和资源控制需求,具有很强的通用性和可扩展性。
  3. 可扩展性 :该算法不仅适用于网络流量控制、API 请求限流和任务调度等常见场景,还可以方便地拓展到其他需要进行资源管理和速率控制的领域,如金融交易系统中的交易频率控制、大数据处理平台中的数据流控制等,展现出广泛的应用前景和良好的可扩展性。

综上所述,Token Bucket 算法是一种功能强大、应用广泛的资源管理和流量控制工具。其在 C++11 中的锁无实现进一步提升了其性能和实用性,为现代软件系统和网络服务的稳定、高效运行提供了有力的支持和保障。

Welcome to follow WeChat official account【程序猿编码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2405149.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux 系统中的算法技巧与性能优化

引言​ Linux 系统以其开源、稳定和高度可定制的特性&#xff0c;在服务器端、嵌入式设备以及开发环境中得到了极为广泛的应用。对于开发者而言&#xff0c;不仅要掌握在 Linux 环境下实现各类算法的方法&#xff0c;更要知晓如何利用系统特性对算法进行优化&#xff0c;以提升…

【C++系列】模板类型特例化

1. C模板类型特例化介绍 ​​定义​​&#xff1a;模板类型特例化&#xff08;Template Specialization&#xff09;是C中为模板的特定类型提供定制实现的机制&#xff0c;允许开发者对通用模板无法处理的特殊类型进行优化或特殊处理。 ​​产生标准​​&#xff1a; C98/03…

K8S认证|CKS题库+答案| 7. Dockerfile 检测

目录 7. Dockerfile 检测 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、修改 Dockerfile 3&#xff09;、 修改 deployment.yaml 7. Dockerfile 检测 免费获取并激活 CKA_v1.31_模拟系统 题目 您必须在以…

基于Scala实现Flink的三种基本时间窗口操作

目录 代码结构 代码解析 (1) 主程序入口 (2) 窗口联结&#xff08;Window Join&#xff09; (3) 间隔联结&#xff08;Interval Join&#xff09; (4) 窗口同组联结&#xff08;CoGroup&#xff09; (5) 执行任务 代码优化 (1) 时间戳分配 (2) 窗口大小 (3) 输出格式…

c++对halcon的动态链接库dll封装及调用(细细讲)

七个部分(是个大工程) 一,halcon封装函数导出cpp的内容介绍 二,c++中对halcon环境的配置 三,在配置环境下验证halcon代码 四,dll项目创建+环境配置 五,编辑dll及导出 六,调用打包好的动态链接库的配置 七,进行测试 一,halcon的封装及导出cpp的介绍 1,我这里…

【优选算法】分治

一&#xff1a;颜色分类 class Solution { public:void sortColors(vector<int>& nums) {// 三指针法int n nums.size();int left -1, right n, i 0;while(i < right){if(nums[i] 0) swap(nums[left], nums[i]);else if(nums[i] 2) swap(nums[--right], num…

【图片识别改名】如何批量将图片按图片上文字重命名?自动批量识别图片文字并命名,基于图片文字内容改名,WPF和京东ocr识别的解决方案

应用场景 在日常工作和生活中&#xff0c;我们经常会遇到需要对大量图片进行重命名的情况。例如&#xff0c;设计师可能需要根据图片内容为设计素材命名&#xff0c;文档管理人员可能需要根据扫描文档中的文字对图片进行分类命名。传统的手动重命名方式效率低下且容易出错&…

RabbitMQ 的高可用性

RabbitMQ 是比较有代表性的&#xff0c;因为是基于主从&#xff08;非分布式&#xff09;做高可用的RabbitMQ 有三种模式&#xff1a;单机模式、普通集群模式、镜像集群模式。 单机模式 单机模式,生产几乎不用。 普通集群模式&#xff08;无高可用性&#xff09; 普通集群模…

AI架构师修炼之道

1 AI时代的架构革命 与传统软件开发和软件架构师相比&#xff0c;AI架构师面临着三重范式转换&#xff1a; 1.1 技术维度&#xff0c;需处理异构算力调度与模型生命周期管理的复杂性&#xff1b; 1.2 系统维度&#xff0c;需平衡实时性与资源约束的矛盾&#xff1b; 1.3 价…

iview组件库:当后台返回到的数据与使用官网组件指定的字段不匹配时,进行修改某个属性名再将response数据渲染到页面上的处理

1、需求导入 当存在前端需要的数据的字段渲染到表格或者是一些公共的表格组件展示数据时的某个字段名与后台返回的字段不一致时&#xff0c;那么需要前端进行稍加处理&#xff0c;而不能直接this.list res.data;这样数据是渲染不出来的。 2、后台返回的数据类型 Datalist(pn) …

服务器 | Centos 9 系统中,如何部署SpringBoot后端项目?

系列文章目录 虚拟机 | Ubuntu 安装流程以及界面太小问题解决 虚拟机 | Ubuntu图形化系统&#xff1a; open-vm-tools安装失败以及实现文件拖放 虚拟机 | Ubuntu操作系统&#xff1a;su和sudo理解及如何处理忘记root密码 文章目录 系列文章目录前言一、环境介绍二、 使用syst…

(2025)Windows修改JupyterNotebook的字体,使用JetBrains Mono

(JetBrains Mono字体未下载就配置,这种情况我不知道能不能行,没做过实验,因为我电脑已经下载了,不可能删了那么多字体做实验,我的建议是下载JetBrains Mono字体,当你使用VsCode配置里面的JetBrains字体也很有用) 首先参考该文章下载字体到电脑上 VSCode 修改字体为JetBrains …

小番茄C盘清理:专业高效的电脑磁盘清理工具

在使用电脑的过程中&#xff0c;我们常常会遇到系统盘空间不足、磁盘碎片过多、垃圾文件堆积等问题&#xff0c;这些问题不仅会导致电脑运行缓慢&#xff0c;还可能引发系统崩溃。为了解决这些问题&#xff0c;小番茄C盘清理应运而生。它是一款专业的C盘清理软件&#xff0c;能…

AUTOSAR实战教程--标准协议栈实现DoIP转DoCAN的方法

目录 软件架构 关键知识点 第一:PDUR的缓存作用 第二:CANTP的组包拆包功能 第三:流控帧的意义 配置过程 步骤0:ECUC模块中PDU创建 步骤1:SoAD模块维持不变 步骤2:DoIP模块为Gateway功能添加Connection ​步骤3:DoIP模块为Gateway新增LA/TA/SA ​步骤4:PDUR模…

【MySQL系列】MySQL 导出表数据到文件

博客目录 一、使用 SELECT INTO OUTFILE 语句基本语法参数详解注意事项实际示例 二、使用 mysqldump 工具基本语法常用选项实际示例 三、使用 MySQL Workbench 导出导出步骤高级选项 四、其他导出方法1. 使用 mysql 命令行客户端2. 使用 LOAD DATA INFILE 的逆向操作3. 使用编程…

vue3:十五、管理员管理-页面搭建

一、页面效果 实现管理员页面,完成管理员对应角色的中文名称显示,实现搜索栏,表格基本增删改查,分页等功能 二、修改问题 1、修改搜索框传递参数问题 (1)问题图示 如下图,之前搜索后,传递的数据不直接是一个value值,而是如下图的格式 查询可知这里传递的数据定义的是…

基于51单片机的红外防盗及万年历仿真

目录 具体实现功能 设计介绍 资料内容 全部内容 资料获取 具体实现功能 具体功能&#xff1a; &#xff08;1&#xff09;实时显示年、月、日、时、分、秒、星期信息&#xff1b; &#xff08;2&#xff09;红外传感器&#xff08;仿真中用按键模拟&#xff09;检测是否有…

【飞腾AI加固服务器】全国产化飞腾+昇腾310+PCIe Switch的AI大模型服务器解决方案

以下是全国产化飞腾AI加固服务器采用飞腾昇腾PCIe Switch解决方案&#xff1a; &#x1f5a5;️ 一、硬件架构亮点 ‌国产算力双擎‌ ‌飞腾处理器‌&#xff1a;搭载飞腾FT2000/64核服务器级CPU&#xff08;主频1.8-2.2GHz&#xff09;&#xff0c;支持高并发任务与复杂计算&a…

应用层协议:HTTPS

目录 HTTPS&#xff1a;超文本传输安全协议 1、概念 2、通信过程及关键技术 2.1 通信过程 1> TLS握手协商&#xff08;建立安全通道&#xff09; 2> 加密数据传输 2.2 关键技术 1> 对称加密算法 2> 非对称加密 3> 对称加密和非对称加密组合 4> 数…

【ArcGIS技巧】—村庄规划规划用地规划状态字段生成工具

"国土空间规划后续也是走向数据治理&#xff0c;数据建库已经是涉及到城市规划、建筑、市政、农业、地理信息、测绘等等方方面面。不得不说以后数据库建设跟维护&#xff0c;是很多专业的必修课。小编就湖南省的村庄规划建库过程中规划用地用海中规划状态字段写了个小工具…