当前位置: 首页 > news >正文

精确掌控并发:滑动时间窗口算法在分布式环境下并发流量控制的设计与实现

这是《百图解码支付系统设计与实现》专栏系列文章中的第(15)篇,也是流量控制系列的第(2)篇。点击上方关注,深入了解支付系统的方方面面。

上一篇介绍了固定时间窗口算法在支付渠道限流的应用以及使用redis实现的核心代码。

本篇重点讲清楚滑动时间窗口算法原理和应用场景,以及使用reids实现的核心代码。

1. 滑动时间窗口原理

滑动窗口算法是一种更为灵活的流量控制方案,它比固定窗口算法能更平滑地处理突发流量。在滑动窗口中,时间窗口是重叠的,这意味着流量的计算是基于过去的一段连续时间内发生的事件。

工作流程:

  1. 窗口定义:确定窗口的大小,例如1秒钟,并设置窗口的滑动间隔,比如100毫秒。
  2. 计数与滑动:每个窗口都有自己的计数器。当一个新请求到达时,增加当前时间窗口及其前面相邻的窗口的计数。
  3. 限制检查:如果任何连续时间段内的请求总数超过阈值,则拒绝新的请求。
  4. 窗口更新:随着时间的推移,不断向前滑动窗口,并更新相应的计数器。

2. 滑动时间窗口在支付系统中的应用场景

滑动时间窗口在支付系统中的应用场景主要也是各种精确限流,比如把前一篇讲的固定时间窗口算法中,我们对外部渠道请求会做限流,那么就可以升级到滑动时间窗口,以提高精度。

只要是API限流,都可以使用。

3. 使用redis实现的核心代码

滑动窗口可以通过队列或循环数组来实现。每个窗口对应队列中的一个元素,记录该窗口期间的请求数。当时间滑动时,更新队列头部的元素,并可能将旧的元素出队

在Redis中,可以使用列表或有序集合来模拟这种滑动窗口。下面是一个Rdis实现的示例,使用有序集合(sorted set)来实现了滑动时间窗口算法:

/*** redis限流操作类*/
@Component
public class RedisLimitUtil {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;// 滑动时间窗口大小private static final long WINDOW_SIZE_IN_SECONDS = 1000;/*** 判断是否限流* 这里不考虑超过long最大值的情况,系统在达到long最大值前就奔溃了。*/public boolean isLimited(String key, String reuqestId, long countLimit) {// 使用Redis的多个命令来实现滑动窗口redisTemplate.zremrangeByScore(key, 0, currentTimeMillis - WINDOW_SIZE_IN_SECONDS);long count = redisTemplate.zcard(key);if (countLimit >= count) {redisTemplate.zadd(key, currentTimeMillis, reuqestId);return true;} else {return false;}}
}

每个请求都以其发生的时间戳作为分数(SCORE)存储在集合中。通过移除旧于当前时间窗口的请求来维护滑动窗口。通过检查集合中的元素数量,以确定是否超过了设定的最大请求数。

  • zremrangeByScore 用于移除窗口之外的旧请求。
  • zcard 获取当前窗口内的请求数量。
  • zadd 将新请求添加到集合中。

使用:PayServiceImpl

/*** 支付服务示例*/
public class PayServiceImpl implements PayService {@Autowiredprivate RedisLimitUtil redisLimitUtil;@Overridepublic PayOrder pay(PayRequest request) {if (isLimited(request)) {throw new RequestLimitedException(buildExceptionMessage(request));}// 其它业务处理... ...}/** 限流判断*/private boolean isLimited(PayRequest request) {// 限流KEY,这里以[业务类型 + 渠道]举例String key = request.getBizType() + request.getChannel();// 限流值Long countLimit = countLimitMap.get(key);// 如果key对应的限流值没有配置,或配置为-1,说明不限流if (null == countLimit || -1 == countLimit) {return false;}return redisLimitUtil.isLimited(key, request.getRequestId(), countLimit);}
}

需要注意一点的是,这次需要传入requestId进去,用于保存这个requestId在redis有序队列里的分数,用于计数和清理。

其它的注释写得比较清楚,没什么补充的。

4. 注意事项

一些分布式服务框架,为了更高的可靠性,他们使用的是本地计算。比如接口限流1000TPS,一共有20台应用服务器,框架就会把计算出每台机器是50个TPS,下发给所有的应用服务器,在服务器上线、下线过程中,可能会有一段时间是不准确的。

但在渠道限流应该中,因为每个渠道的流量都不太高,所以可以使用这种redis方案。且精度更高,不受应用服务器的上、下线影响。

另外,在分布式系统中,需要确保不同节点之间的时间同步,以保证流量计算的准确性。如果应用服务器之间的时间不同步,那么流量就会计算错误。

5. 结束语

分布式流控有很多实现方案,通过把固定时间窗口算法升级为滑动时间窗口算法,我们对流量控制的精度会大幅提升。

下一篇会介绍漏桶原理及实现。漏桶和令牌桶的特点是请求进来先保存起来,然后按一定的速度发送出,而不是超过阀值就拒绝。

6. 传送门

支付系统设计与实现是一个专业性非常强的领域,里面涉及到的很多设计思路和理论也可以应用到其它行业的软件设计中,比如幂等性,加解密,领域设计思想,状态机设计等。

在《百图解码支付系统设计与实现》的知识宇宙,每一篇深入浅出的文章都是一颗既独立但又彼此强关联的星球,有必要提供一个传送门以便让大家即刻到达想要了解的文章。

专栏地址百图解码支付系统设计与实现
领域相关
支付行业黑话:支付系统必知术语一网打尽
跟着图走,学支付:在线支付系统设计的图解教程
支付交易的三重奏:收单、结算与拒付在支付系统中的协奏曲
在线支付系统的精英搭档:深入剖析收银核心与支付引擎的协同作战(一)
在线支付系统的精英搭档:深入剖析收银核心与支付引擎的协同作战(二)

技术专题
交易流水号的艺术:掌握支付系统的业务ID生成指南
揭密支付安全:为什么你的交易无法被篡改
金融密语:揭秘支付系统的加解密艺术
支付系统日志设计完全指南:构建高效监控和问题排查体系的关键基石
避免重复扣款:分布式支付系统的幂等性原理与实践
支付系统的心脏:简洁而精妙的状态机设计与核心代码实现
精确掌控并发:分布式环境下并发流量控制的设计与实现(一)
精确掌控并发:分布式环境下并发流量控制的设计与实现(二)
金融疆界:在线支付系统渠道网关的创新设计(一)

相关文章:

精确掌控并发:滑动时间窗口算法在分布式环境下并发流量控制的设计与实现

这是《百图解码支付系统设计与实现》专栏系列文章中的第&#xff08;15&#xff09;篇&#xff0c;也是流量控制系列的第&#xff08;2&#xff09;篇。点击上方关注&#xff0c;深入了解支付系统的方方面面。 上一篇介绍了固定时间窗口算法在支付渠道限流的应用以及使用redis…...

Python展示 RGB立方体的二维切面视图

代码实现 import numpy as np import matplotlib.pyplot as plt# 生成 24-bit 全彩 RGB 立方体 def generate_rgb_cube():# 初始化一个 256x256x256 的三维数组rgb_cube np.zeros((256, 256, 256, 3), dtypenp.uint8)# 填充立方体for r in range(256):for g in range(256):fo…...

03 顺序表

目录 线性表顺序表练习 线性表(Linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串。。。 线性表在逻辑上时线性结构&#xff0c;是连续的一条直线。但在物理结…...

2023年全球软件开发大会(QCon北京站2023)9月:核心内容与学习收获(附大会核心PPT下载)

随着科技的飞速发展&#xff0c;全球软件开发大会&#xff08;QCon&#xff09;作为行业领先的技术盛会&#xff0c;为世界各地的专业人士提供了交流与学习的平台。本次大会汇集了全球的软件开发者、架构师、项目经理等&#xff0c;共同探讨软件开发的最新趋势、技术与实践。本…...

ChatGPT 和 文心一言 的优缺点及需求和使用场景

ChatGPT和文心一言是两种不同的自然语言生成模型&#xff0c;它们有各自的优点和缺点。 ChatGPT&#xff08;Generative Pre-trained Transformer&#xff09;是由OpenAI开发的生成式AI模型&#xff0c;它在庞大的文本数据集上进行了预训练&#xff0c;并可以根据输入生成具有上…...

架构师之超时未支付的订单进行取消操作的几种解决方案

今天给大家上一盘硬菜&#xff0c;并且是支付中非常重要的一个技术解决方案&#xff0c;有这块业务的同学注意自己尝试一把哈&#xff01; 一、需求如下&#xff1a; 生成订单30分钟未支付&#xff0c;自动取消 生成订单60秒后,给用户发短信 对上述的需求&#xff0c;我们给…...

【容器固化】 OS技术之OpenStack容器固化的实现原理及操作

1. Docker简介 要学习容器固化&#xff0c;那么必须要先了解下Docker容器技术。Docker是基于GO语言实现的云开源项目&#xff0c;通过对应用软件的封装、分发、部署、运行等生命周期的管理&#xff0c;达到应用组件级别的“一次封装&#xff0c;到处运行”。这里的应用软件&am…...

设置 SSH 通过密钥登录

我们一般使用 PuTTY 等 SSH 客户端来远程管理 Linux 服务器。但是&#xff0c;一般的密码方式登录&#xff0c;容易有密码被暴力破解的问题。所以&#xff0c;一般我们会将 SSH 的端口设置为默认的 22 以外的端口&#xff0c;或者禁用 root 账户登录。其实&#xff0c;有一个更…...

1.6 面试经典150题 - 买卖股票的最佳时机

买卖股票的最佳时机 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔交易…...

locust快速入门--使用分布式提高测试压力

背景&#xff1a; 使用默认的locust启动命令进行压测时&#xff0c;尽管已经将用户数设置大比较大&#xff08;400&#xff09;&#xff0c;但是压测的时候RPS一直在100左右。需要增加压测的压力。 问题原因&#xff1a; 如果你是通过命令行启动的或者参考之前文章的启动方式…...

K8s(三)Pod资源——pod亲和性与反亲和性,pod重启策略

目录 pod亲和性与反亲和性 pod亲和性 pod反亲和性 pod状态与重启策略 pod状态 pod重启策略 本文主要介绍了pod资源与pod相关的亲和性&#xff0c;以及pod的重启策略 pod亲和性与反亲和性 pod亲和性&#xff08;podAffinity&#xff09;有两种 1.podaffinity&#xff0c;…...

免费的域名要不要?

前言 eu.org的免费域名相比于其他免费域名注册服务&#xff0c;eu.org的域名后缀更加独特。同时&#xff0c;eu.org的域名注册也比较简单&#xff0c;只需要填写一些基本信息&#xff0c;就可以获得自己的免费域名。 博客地址 免费的域名要不要&#xff1f;-雪饼前言 eu.org…...

高通sm7250与765G芯片是什么关系?(一百八十一)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…...

[Python进阶] Python操作MySQL数据库:pymysql

7.7 操作MySQL数据库&#xff1a;pymysql 7.7.1 准备工作(创建mysql数据库) PHPStudy介绍&#xff1a; phpstudy是一款非常有用的PHP开发工具&#xff0c;旨在帮助开发者更加便捷地进行PHP程序的开发与调试。它提供了一个友好的图形用户界面&#xff0c;使得用户能够方便地进…...

Vue3实现带点击外部关闭对应弹出框(可共用一个变量)

首先&#xff0c;假设您在单文件组件(SFC)中使用了Vue3&#xff0c;并且有两个div元素分别通过v-if和v-else来切换显示一个带有.elpopver类的弹出组件。在这种情况下&#xff0c;每个弹出组件应当拥有独立的状态管理&#xff08;例如&#xff1a;各自的isOpen变量&#xff09;。…...

可视化试题(一)

1. 从可视化系统设计的角度出发&#xff0c;通常需要根据系统将要完成的任务的类型选择交互技术。按照任务类型分类可以将数据可视化中的交互技术分为选择、&#xff08; 重新配置 &#xff09;、重新编码、导航、关联、&#xff08; 过滤 &#xff09;、概览和细节等八…...

RHCE 【在openEuler系统中搭建基本论坛(网站)】

目录 网站需求&#xff1a; 准备工作&#xff1a; 1.基于域名[www.openlab.com](http://www.openlab.com)可以访问网站内容为 welcome to openlab!!! 测试&#xff1a; 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c;基于[www.openla…...

20240112让移远mini-PCIE接口的4G模块EC20在Firefly的AIO-3399J开发板的Android11下跑通【DTS部分】

20240112让移远mini-PCIE接口的4G模块EC20在Firefly的AIO-3399J开发板的Android11下跑通【DTS部分】 2024/1/12 16:20 https://blog.csdn.net/u010164190/article/details/79096345 [Android6.0][RK3399] PCIe 接口 4G模块 EC20 调试记录 https://blog.csdn.net/hnjztyx/artic…...

日志采集传输框架之 Flume,将监听端口数据发送至Kafka

1、简介 Flume 是 Cloudera 提供的一个高可用的&#xff0c;高可靠的&#xff0c;分布式的海量日志采集、聚合和传 输的系统。Flume 基于流式架构&#xff0c;主要有以下几个部分组成。 主要组件介绍&#xff1a; 1&#xff09;、Flume Agent 是一个 JVM 进程&#xf…...

关于Vue前端接口对接的思考

关于Vue前端接口对接的思考 目录概述需求&#xff1a; 设计思路实现思路分析1.vue 组件分类和获取数值的方式2.http 通信方式 分类 如何对接3.vue 组件分类和赋值方式&#xff0c; 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your p…...

【设计模式之美】SOLID 原则之三:里式替换(LSP)跟多态有何区别?如何理解LSP中子类遵守父类的约定

文章目录 一. 如何理解“里式替换原则”&#xff1f;二. 哪些代码明显违背了 LSP&#xff1f;三. 回顾 一. 如何理解“里式替换原则”&#xff1f; 子类对象能够替换程序中父类对象出现的任何地方&#xff0c;并且保证原来程序的逻辑行为不变及正确性不被破坏。 里氏替换原则…...

代码随想录第六十三天——被围绕的区域,太平洋大西洋水流问题,最大人工岛

leetcode 130. 被围绕的区域 题目链接&#xff1a;被围绕的区域 步骤一&#xff1a;深搜或者广搜将地图周边的’O’全部改成’A’ 步骤二&#xff1a;遍历地图&#xff0c;将’O’全部改成’X’&#xff0c;将’A’改回’O’ class Solution { private:int dir[4][2] {-1, 0…...

Docker 项目如何使用 Dockerfile 构建镜像?

1、Docker 和 Dockerfile 的重要性 1.1、Docker 简介&#xff1a;讲述 Docker 的起源、它是如何革新现代软件开发的&#xff0c;以及它为开发者和运维团队带来的好处。重点强调 Docker 的轻量级特性和它在提高应用部署、扩展和隔离方面的优势。 本文已收录于&#xff0c;我的…...

实践学习PaddleScience飞桨科学工具包

实践学习PaddleScience飞桨科学工具包 动手实践&#xff0c;在实践中学习&#xff01;本项目可以在AIStudio平台一键运行&#xff01;地址&#xff1a;https://aistudio.baidu.com/projectdetail/4278591 本项目第一次执行会报错&#xff0c;再执行一次即可。若碰到莫名其妙的…...

Vue 中修改 Element 组件的 下拉菜单(Dropdown) 的样式

Vue 中修改 Element 组件的 下拉菜单(Dropdown) 的样式 今天在项目中碰到一个 UI 改造的需求&#xff0c;需要根据设计图把页面升级成 UI 设计师提供的设计图样式。 到最后页面改造完了&#xff0c;但是 UI 提供的下拉菜单样式全部是黑色半透明的&#xff0c;只能硬着头皮改了。…...

达梦数据库主备集群

1&#xff1a;服务器硬件需求 按实际业务需求&#xff0c;选择合适的服务器&#xff0c;准备 3 台服务器&#xff0c;一台主库服务器&#xff0c;一台备库服务器&#xff0c;一台监视器服务器&#xff0c;服务器参数建议如下&#xff1a; 硬件要求物理内存>16 GB交换区Swa…...

Spark Doris Connector 可以支持通过 Spark 读取 Doris 数据类型不兼容报错解决

1、版本介绍&#xff1a; doris版本&#xff1a; 1.2.8Spark Connector for Apache Doris 版本&#xff1a; spark-doris-connector-3.3_2.12-1.3.0.jar:1.3.0-SNAPSHOTspark版本&#xff1a;spark-3.3.1 2、Spark Doris Connector Spark Doris Connector - Apache Doris 目…...

深入理解 go chan

go 里面&#xff0c;在实际程序运行的过程中&#xff0c;往往会有很多协程在执行&#xff0c;通过启动多个协程的方式&#xff0c;我们可以更高效地利用系统资源。 而不同协程之间往往需要进行通信&#xff0c;不同于以往多线程程序的那种通信方式&#xff0c;在 go 里面是通过…...

java+vue基于Spring Boot的渔船出海及海货统计系统

该渔船出海及海货统计系统采用B/S架构、前后端分离进行设计&#xff0c;并采用java语言以及springboot框架进行开发。该系统主要设计并完成了管理过程中的用户注册登录、个人信息修改、用户信息、渔船信息、渔船航班、海货价格、渔船海货、非法举报、渔船黑名单等功能。该系统操…...

Linux第25步_在虚拟机中备份“ST官方的TF-A源码”

TF-A是ARM公司提供的&#xff0c;ST公司通过修改它&#xff0c;做了一个自己的TF-A代码。因为在后期开发中&#xff0c;若硬件被改变了&#xff0c;我们需要通过修改"ST官方的TF-A源码"就可以自己的TF-A代码了。为了防止源文件被误改了&#xff0c;我们需要将"S…...

李沧网站建设公司/seo排名诊断

点击↑↑技成培训 &#xff0c;关注并置顶即可长期免费订阅20万工控人关注的微信平台&#xff1a;技术分享、学习交流、工控视频当一个或者多个指令(程序)重复多次(次数可知)时&#xff0c;可使用FOR指令。FOR为有限次循环指令。如上图&#xff0c;程序的执行过程主要分为3个步…...

政府网站建设赏析/百度竞价广告投放

RSA因子->der格式&#xff08;按照一定格式组合&#xff09;->ASN.1格式&#xff08;base64&#xff09;->pem或crt格式&#xff08;添加头尾信息&#xff09;...

深圳住建厅官方网站/web网页制作成品免费

广义表是数据结构中非常关键的一部分&#xff0c;它的学习对于树和二叉树有很大的起承作用。那么&#xff0c;它是怎么实现的呢&#xff1f;广义表的实现应用到了一个很熟悉的算法——递归。来看看它的代码吧&#xff01;#pragma once #include<iostream> #include<ca…...

网站上papi酱做的音频/搜狗站长平台打不开

Web基本笔记~12.引用数据类型 上一期 引用类型的值&#xff08;对象&#xff09;是引用类型的一个实例。在JavaScript中&#xff0c;引用类型是一种数据结构&#xff0c;用于将数据和功能组织在一起。它也常被称为类&#xff0c;但这种称呼并不妥当。尽管JavaScript从技术上讲…...

网站用什么布局/洛阳网站seo

前言&#xff1a;似乎直接使用 anaconda Navigator 或者使用 conda 安装 libsvm无效&#xff0c;故而转而手动安装&#xff0c;安装步骤非常简洁。安装 libsvm 和安装 liblinear 方法完全相同&#xff0c;下面只以为anaconda手动安装 liblinear 为例进行描述。 下载 libsvm 和…...

dw做的网站怎样做成手机版的/女教师遭网课入侵视频大全

CSS部分&#xff1a; 一、CSS优先级&#xff1a; !important > 行内样式 > ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默 认属性同一级别。 二、盒子模型&#xff1a; IE盒子模型&#xff1a;width border padding 内容宽度 W3C标准盒子模型…...