分布式限流——Redis + Lua实现滑动窗口算法

Zset(有序集合)在Redis中用来实现滑动窗口限流的主要思路是利用其自动排序和可过期成员的特点:

  1. 初始化及数据结构选择

    • 为需要限流的接口或服务创建一个唯一的键(key)对应一个Zset。
    • Zset中的每个成员通常是请求的唯一标识符(如UUID或其他唯一字符串),用于区分不同的请求。
    • Zset的score字段用来存储每个请求的时间戳,由于Redis中的score支持浮点数,通常会存储Unix时间戳(秒级或毫秒级精度)。
  2. 添加请求记录

    • 当有新的请求到来时,将当前时间戳作为score,添加到Zset中,同时成员可以是任意唯一标识符,或者是省略,仅保留score的有序排列。
  3. 检查窗口内的请求数量

    • 根据限流策略(比如每分钟100次),计算出当前时间戳对应的窗口开始时间(当前时间减去窗口长度)。
    • 使用Zset的ZCARD命令,查找score在窗口范围内的元素数量。
    • 如果数量超过设定的阈值,则拒绝新请求。
  4. 移除过期请求记录

    • 可以结合Zset的过期功能(TTL)来自动清理超时的请求记录,也可以在每次处理请求时手动清理窗口开始时间之前的所有记录,这样能确保Zset只包含当前窗口内的请求。
  5. 原子操作与并发控制

    • 在高并发场景下,为了保证限流逻辑的正确执行,可以通过编写Lua脚本来实现一系列操作的原子性执行,避免因并发问题造成的计数不准确。

通过以上步骤,Zset能够有效地维护一个时间窗口内的请求数量,从而达到限流的目的,确保服务在高峰期不会因为过多请求而导致性能瓶颈。

以下是一个基于Redis Zset实现滑动窗口限流的Lua脚本示例,假设我们希望限制在过去的10秒内某个服务的请求数量不超过100个:

-- KEYS[1] 是服务的唯一标识符
-- ARGV[1] 是窗口大小(秒)
-- ARGV[2] 是限流阈值(请求次数)
-- ARGV[3] 是当前请求的时间戳(毫秒级)-- 获取窗口开始时间戳
local windowStart = tonumber(ARGV[3]) - tonumber(ARGV[1]) * 1000-- 移除窗口开始时间之前的请求记录
redis.call('ZREMRANGEBYSCORE', KEYS[1], 0, windowStart)-- 添加当前请求记录
redis.call('ZADD', KEYS[1], ARGV[3], '')-- 获取窗口内的请求数量
local requestCount = redis.call('ZCARD', KEYS[1])-- 判断是否超过限流阈值
if requestCount > tonumber(ARGV[2]) then-- 如果超过阈值,删除刚添加的请求记录(模拟请求被拒绝)redis.call('ZREM', KEYS[1], '')return 0 -- 返回0表示请求被限流
elsereturn 1 -- 返回1表示请求被允许
end

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

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

相关文章

JAVA基础08- 继承,重写,super以及this

目录 继承(extends) 定义 说明 作用 方法的重写 定义 重写关键点 方法重写与重载的区别 练习 练习1(方法继承与重写的简单练习) 练习2(方法继承与重写的进阶练习) This的使用 定义 作用以及注…

基于SpringBoot+Vue的IT技术交流平台(源码+文档+包运行)

一.系统概述 我国科学技术的不断发展,计算机的应用日渐成熟,其强大的功能给人们留下深刻的印象,它已经应用到了人类社会的各个层次的领域,发挥着重要的不可替换的作用。信息管理作为计算机应用的一部分,使用计算机进行…

leetcode-分割链表

题目 面试题 02.04. 分割链表 提示 给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你不需要 保留 每个分区中各节点的初始相对位置。 示例 1: 输入&#xff…

搜维尔科技:【工业仿真】煤矿安全知识基础学习VR系统

产品概述 煤矿安全知识基础学习VR系统 系统内容: 煤矿安全知识基础学习VR系统内容包括:下井流程(正确乘坐罐笼、班前会、井下行走注意事项、工作服穿戴、入井检身及人员清点、下井前准备工作、提升运输安全);运煤流程…

SpringBoot集成RockerMQ

1.引入依赖 <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.2.0</version> </dependency>2.配置服务器地址 #Rocketmq配置 rocketmq.name-server192…

专业清洁工匠服务网站模板 html网站

目录 一.前言 二.页面展示 三.下载链接 一.前言 该HTML代码生成了一个网页&#xff0c;包括以下内容&#xff1a; 头部信息&#xff1a;指定了网页的基本设置和元数据&#xff0c;例如字符编码、视口大小等。CSS文件&#xff1a;引入了多个CSS文件&#xff0c;用于设置网页…

EI级 | Matlab实现VMD-TCN-LSTM-MATT变分模态分解卷积长短期记忆神经网多头注意力多变量时间序列预测

EI级 | Matlab实现VMD-TCN-LSTM-MATT变分模态分解卷积长短期记忆神经网多头注意力多变量时间序列预测 目录 EI级 | Matlab实现VMD-TCN-LSTM-MATT变分模态分解卷积长短期记忆神经网多头注意力多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实…

动手写sql 《牛客网80道sql》

第1章&#xff1a;SQL编写基础逻辑和常见问题 基础逻辑 SELECT语句: 选择数据表中的列。FROM语句: 指定查询将要从哪个表中检索数据。WHERE语句: 过滤条件&#xff0c;用于提取满足特定条件的记录。GROUP BY语句: 对结果进行分组。HAVING语句: 对分组后的结果进行条件过滤。O…

【STM32】嵌入式实验二 GPIO 实验 (前三个设计)

1&#xff0e; 按键亮灯 设计 GPIO 实验项目 1&#xff0c;功能&#xff1a;当按键 KB1 按下时&#xff0c;实验板上全彩发光二极管周边 的发光二极管全亮&#xff0c;当按键 KB2 按下时跑马灯 D0 闪亮。 实验要求基于寄存器的GPIO配置&#xff0c;所以需要手动操作寄存器来配…

联想小新Air14-2019锐龙版更换硬盘

首先打下D面所有螺丝&#xff08;内六角螺丝&#xff0c;需要准备螺丝刀&#xff09;&#xff0c;然后从下方翘起整个D面打开如下图 原装为2280长度的海力士硬盘&#xff0c;有空余的2242长度硬盘位 更换前断电&#xff0c;建议拆下电池&#xff08;扣下电池排线后不好安装&am…

每日OJ题_完全背包④_力扣279. 完全平方数(一维和二维)

目录 力扣279. 完全平方数 问题解析 解析代码 优化代码&#xff08;相同子问题分析和滚动数组&#xff09; 力扣279. 完全平方数 279. 完全平方数 难度 中等 给你一个整数 n &#xff0c;返回 和为 n 的完全平方数的最少数量 。 完全平方数 是一个整数&#xff0c;其值…

百科不全书之 docker记录

docker记录 1 参考文件2. Docker简介与虚拟机的区别 1 参考文件 参考视频&#xff1a;B站【GeekHour】30分钟Docker入门教程: link 2. Docker简介 Docker是一个用于构建运行 传送 应用程序的平台。 与虚拟机的区别 虚拟机使用了一种叫做虚拟化的技术。每台虚拟机需要占…

固定测斜仪:工程观测的精密利器

在工程观测测量领域&#xff0c;固定测斜仪扮演着至关重要的角色。固定测斜仪&#xff0c;凭借其耐冲击型倾斜传感器、出色的可靠性、快速稳定的特点&#xff0c;以及简洁的安装和智能识别功能&#xff0c;已成为行业内重要工具。其输出信号为RS485数字量&#xff0c;可直接显示…

使用electron打包vuecli创建的项目

下面是我打包的时候才过的所有的坑&#x1f4a3;&#xff1a; 首先创建一个vue2的空项目&#xff0c;如果全局安装的vue-cli版本太低&#xff0c;低于3就无法使用vue create命令&#xff0c;必须使用uninstall将之前的卸载掉&#xff0c;在重现安装&#xff0c;之后的就是最近…

握手问题(蓝桥杯)

文章目录 握手问题【问题描述】答案&#xff1a;1204解题思路模拟 握手问题 【问题描述】 小蓝组织了一场算法交流会议&#xff0c;总共有 50 人参加了本次会议。在会议上&#xff0c;大家进行了握手交流。按照惯例他们每个人都要与除自己以外的其他所有人进行一次握手&#…

Scrapy框架内存泄漏问题及解决

说明&#xff1a;仅供学习使用&#xff0c;请勿用于非法用途&#xff0c;若有侵权&#xff0c;请联系博主删除 作者&#xff1a;zhu6201976 一、问题背景及原因 官方文档&#xff1a;Debugging memory leaks — Scrapy 2.11.1 documentation Scrapy是一款功能强大的网络爬虫框…

SpringMVC 常用注解介绍

Spring MVC 常用注解介绍 文章目录 Spring MVC 常用注解介绍准备1. RequestMapping1.1 介绍2.2 注解使用 2. 请求参数2.1 传递单个参数2.2 传递多个参数2.3 传递对象2.4 传递数组 3. RequestParam3.1 注解使用3.2 传入集合 4. RequestBody5. PathVariable6. RequestPart7. Rest…

k8s使用harbor私有仓库镜像 —— 筑梦之路

官方文档: Secret | Kubernetes ImagePullSecrets的设置是kubernetes机制的另一亮点&#xff0c;习惯于直接使用Docker Pull来拉取公共镜像&#xff0c;但非所有容器镜像都是公开的。此外&#xff0c;并不是所有的镜像仓库都允许匿名拉取&#xff0c;也就是说需要身份认证&…

23 种设计模式

设计模式 1、工厂方法 消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。 2、建造者模式 建造模式:将产品的内部表象和产品的生成过程分割开来,从而使一…

【electron3】electron将数据写入本地数据库

安装 yarn add sqlite3 --save连接并调用数据库&#xff0c;创建表 createDB.ts文件内容 const sqlite3 require(sqlite3) const NODE_ENV process.env.NODE_ENV const path require(path) const { app } require(electron) let DB_PATH path.join(app.getAppPath(), /…