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

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

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

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

相关文章

消息的发送与接收

消息的发送与接收 消息的发送与接收不仅仅是在于聊天功能的实现。其实还有很多种情况也算"消息的发送与接收"。而且我们还可以通过多种方法去实现。我们可以基于实际情况来选择。 WebSocket实现 node做后端。找了好多&#xff0c;前端页面总是用到了jQuery&#x…

lvgl简介

LVGL&#xff08;Light and Versatile Graphics Library&#xff09;是一个开源的图形用户界面库&#xff0c;旨在提供轻量级、可移植、灵活和易于使用的图形用户界面解决方案。 它适用于嵌入式系统&#xff0c;可以在不同的操作系统、微控制器和图形加速器上运行。LVGL的核心…

1.go安装及相关配置

目录 概述下载基本命令Go build环境设置 结束 概述 下载 官网速递 选择 1.20.x 一个是因为是次新版本&#xff0c;另一个&#xff0c;mac 系统是 10.13.6 &#xff0c;1.20.x 是最后一个支持此版本的。 环境变量 GOROOT go的安装目录(将go安装到哪里 which go、cat /etc/p…

高并发IO底层原理

1 概述 IO底层原理是隐藏在Java编程知识之下的基础知识&#xff0c;是开发人员必须掌握的基本原理。本文从操作系统的底层原理入手&#xff0c;通过图文的方式为大家深入剖析高并发IO的底层原理&#xff0c;并介绍如何通过设置来让操作系统支持高并发。 2 IO读写的基本原理 为…

文件模块常用api

文件模块常用api 文件夹常用操作 文件夹操作 fs.mkdir fs.rmdir 需要是空目录 题目&#xff1a;递归删除目录* 串行/并行删除文件*

【电商API】DIY网络爬虫收集电商数据

DIY网络爬虫收集电商数据 网络爬虫是最常见和使用最广泛的数据收集方法。DIY网络爬虫确实需要一些编程知识&#xff0c;但整个过程比一开始看起来要简单得多。 当然&#xff0c;爬虫的有效性取决于许多因素&#xff0c;例如目标的难度、网站方的反爬虫措施等。如果将网络抓取用…

机器学习根据金标准标记数据-九五小庞

根据金标准标记数据是一种在机器学习和数据科学中常见的操作&#xff0c;主要用于评估分类模型的性能。其基本步骤如下&#xff1a; 收集数据&#xff1a;首先需要收集相关领域的原始数据&#xff0c;这些数据通常来自不同的来源和渠道。数据清洗和预处理&#xff1a;在这一步…

soft212期末

文章目录 安卓填空题选择题 C# 安卓 Dalvik中得到Dx工具会把部分class文件转换成dex文件。 如果希望在XML布局文件中调用颜色资源&#xff0c;可以使用color调用 Android程序入口的Activity是在AndroidManifest.xml文件中注册的 Android中查看应用程序日志的工具是LogCat Dal…

JavaScript面向对象之实践项目

1、cat项目 &#xff08;1&#xff09;需要修改的原代码 &#xff08;2&#xff09;修改要求 使用括号表示法将name属性的值存储在变量catName中。使用点表示法运行greeting()方法。将color属性值更新为白。重写greeting() 方法&#xff0c;使它的问候语为"孟买猫碳头对…

良心推荐!几款收藏的神级IDEA插件分享

本文已收录至Github&#xff0c;推荐阅读 &#x1f449; Java随想录 微信公众号&#xff1a;Java随想录 文章目录 CodeGlanceGsonFormatPOJO to JsonRainbow BracketsTranslationLombokMaven HelperAlibaba Java Code GuidelinesGenerateAllSetterMybatisXChinese (Simplified…

Tomcat10.X部署老版本axis2 webservice项目不生效

目录 一、使用场景 二、问题描述 三、原因排查 四、解决方案 一、使用场景 原来项目是OpenJDK8tomcat9构建&#xff0c;现在需要升级到OpenJDK17tomcat10的组合。原来的webservice项目打包成aar格式&#xff0c;通过axis2部署在tomcat上。 二、问题描述 在配置好jdk和to…

【软件测试学习笔记1】测试基础

1.软件测试的定义 软件的定义&#xff1a;控制计算机硬件工作的工具 软件的基本组成&#xff1a;页面客户端&#xff0c;代码服务器&#xff0c;数据服务器 软件产生的过程&#xff1a;需求产生&#xff08;产品经理&#xff09;&#xff0c;需求文档&#xff0c;设计效果图…

NEAU_Python程序设计结课作业

1.身份证号合法性判别 【问题描述】我国身份证号码由数字与字母混合组成。早期身份证由15位数字构成。后来考虑到千年虫问题(&#xff08;15位的身份证号码只能为150c年1月1日到9年12月31日出生的人确号)&#xff0c;所以又增加了18位身份证号码编号规则。最后—位(第18位)校验…

用二维码介绍产品详情,扫码查看图文并茂的宣传册

传统的产品宣传方式&#xff0c;往往以产品手册、宣传单等纸质物料为主&#xff0c;更新成本高昂&#xff0c;一旦修改内容&#xff0c;就必须重新印刷&#xff0c;而且不易携带和保存&#xff0c;影响宣传效果和客户体验。 为了避免上述问题&#xff0c;可以在草料上搭建产品…

【树莓派】网线远程连接电脑和树莓派,实现SSH连接

目录 1、硬件连接&#xff1b; 2、电脑端&#xff1a; 3、查找树莓派的IP地址 4、开启树莓派的SSH接口 5、putty 6、命令行 参考文章 通过网线连接笔记本与树莓派 开启SSH和VNC功能 无显示器安装树莓派 实现&#xff1a;打开putty输入树莓派地址使用ssh方式登陆&…

java小游戏——动漫美女拼图

1&#xff1a;继承 1.1 继承概述 首先&#xff0c;我们来说一下&#xff0c;什么是继承&#xff1a; 继承是面向对象三大特征之一(封装&#xff0c;继承和多态) 可以使得子类具有父类的属性和方法&#xff0c;还可以在子类中重新定义&#xff0c;追加属性和方法 也就是说&…

【办公技巧】ppt修改全部字体怎么改?

制作完PPT之后&#xff0c;想要更换ppt中的字体&#xff0c;有没有什么快捷的方法呢&#xff1f;今天分享两个方法&#xff0c;一键修改ppt文件字体。 方法一&#xff1a; 找到功能栏中的编辑选项卡&#xff0c;点击替换 – 替换字体&#xff0c;在里面选择我们想要替换的字体…

【DolphinScheduler】datax读取hive分区表时,空分区、分区无数据任务报错问题解决

问题背景&#xff1a; 最近在使用海豚调度DolphinScheduler的Datax组件时&#xff0c;遇到这么一个问题&#xff1a;之前给客户使用海豚做的离线数仓的分层搭建&#xff0c;一直都运行好好的&#xff0c;过了个元旦&#xff0c;这几天突然在数仓做任务时报错&#xff0c;具体报…

JUC之锁

乐观锁和悲观锁 悲观锁 当一个线程在操作资源的时候&#xff0c;会悲观的任务有其他的线程会来抢占该资源&#xff0c;因此会在操作资源前进行加锁&#xff0c;避免其他线程抢占。 Synchronized关键字和Lock实现类就是悲观锁。 显示的锁定资源后再对资源进行操作。 使用场景&…

生日视频模板-试试这样制作

视频制作已经成为表达情感、记录生活的重要方式。尤其在生日这样的特殊日子&#xff0c;一份个性化的视频祝福不仅能让人感到温馨&#xff0c;还能成为长久珍藏的回忆。那么&#xff0c;如何快速制作出精美的生日模版视频呢&#xff1f;下面就给大家介绍几种可以制作生日模版的…