利用 Redis 和 Lua 实现高效的限流功能

简介

在现代系统中,限流是一种重要的机制,用于控制服务端的流量并保护系统免受恶意攻击或请求泛滥的影响。本文将介绍如何利用 Redis 和 Lua 结合实现高效的限流功能。

一、什么是限流

限流指的是对系统中的请求进行控制和调节,确保系统在承受压力时能够正常运行,不会因为突然的大量请求导致系统宕机或服务质量下降。限流在系统中具有至关重要的作用,可以平稳地处理请求流量,防止系统过载。

二、什么是Redis

Redis是一个高性能的内存数据库,具有快速的读写速度和丰富的数据结构支持。在限流场景中,Redis可以作为一个高效的缓存和计数工具,帮助实现限流功能。

三、什么是lua

Lua是一种轻量级的脚本语言,它具有简洁的语法和高效的执行性能。

四、限流要用lua+Redis而不用Java、Python 等语言呢?

  • 性能和原子性: Lua脚本可以在Redis服务器端原子性地执行多个命令,避免了多次网络通信的开销,提高了性能和原子性。相比之下,用Java或Python实现的限流算法需要多次与Redis进行通信,性能相对较低。

  • 便捷性: Lua脚本可以直接在Redis服务器端执行,无需额外部署其他语言的运行环境,更加灵活和便捷。

  • Redis支持: Redis天然支持Lua脚本,可以直接执行,不需要额外的配置和插件。而如果使用Java或Python,需要额外的库或框架来与Redis进行交互。

五、限流算法选择

5.1 令牌桶算法

令牌桶算法中,存在一个令牌桶,可以往桶中添加令牌。每个令牌代表一个处理请求的许可。如果请求到了,桶中有足够的令牌,择允许处理该请求,同时消耗相应数量的令牌。如果桶中没有足够的令牌,则拒接该请求或将请求放入队列等待令牌。

5.2 漏桶算法

漏桶算法中,存在一个固定容量的漏桶,以固定的速率处理请求。如果请求到来,放入漏桶中,如果漏桶已满,则拒绝请求,如果漏桶未满,则按照固定的速率处理请求。

六、lua+Redis实现令牌桶算法

local key = KEYS[1] -- 获取传入lua脚本的第一个keys参数,用作存储令牌数目的键名
local limit = tonumber(ARGV[1]) -- 将传入lua脚本的第一个ARGV参数转换为整数,表示桶的容量
local current = tonumber(redis.call('get', key) or "0")
-- 通过Redis的GET命令获取当前令牌桶中的令牌数量,如果没有获取到则默认为0,并将其转换为整数。
​
if current + 1 > limit then -- 判断当前令牌桶中的令牌数量加1后是否超过阈值return 0 -- 超过表示请求被限流,返回0
elseredis.call('INCR', key) -- 通过Redis的INCR命令将令牌桶中的数量加1,表示通过了一个请求redis.call('EXPIRE', key, ARGV[2]) -- 设置令牌桶的过期时间为ARGV 参数中指定的时间return 1  -- 返回1,表示通过限流检查
end

七、lua+Redis实现漏桶算法

local key = KEYS[1] -- 限流器的键名
local capacity = tonumber(ARGV[1]) -- 漏桶的容量
local rate = tonumber(ARGV[2]) -- 漏桶的速率
local now = tonumber(ARGV[3]) -- 当前时间戳
local interval = 1 / rate -- 时间间隔,即每个请求需要等待的时间
​
local water = tonumber(redis.call('get', key) or "0") -- 获取漏桶中的水滴数量
local lastLeakTime = tonumber(redis.call('get', key .. ':last_leak_time') or "0") -- 上次漏水的时间戳
​
local elapsed = math.max(0, now - lastLeakTime) -- 计算当前时间与上次漏水的时间间隔
​
water = water - elapsed * rate -- 根据时间间隔计算漏水数量,并更新漏桶中的水滴数量
​
if water < 0 thenwater = 0 -- 水滴数量不会低于0
end
​
water = water + 1 -- 新的请求加入漏桶中
​
if water > capacity thenreturn 0 -- 漏桶已满,拒绝请求
elseredis.call('set', key, water) -- 更新漏桶中的水滴数量redis.call('set', key .. ':last_leak_time', now) -- 更新上次漏水的时间戳return interval -- 返回请求需要等待的时间间隔
end

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

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

相关文章

Cluade3干货:超越GPT,模型特点分析+使用教程|2024年3月更新

就在刚刚&#xff0c;Claude 发布了最新的大模型 Claude3&#xff0c;并且一次性发布了三个模型&#xff0c;分别是 Claude 3 Haiku&#xff1a;&#xff08;日本俳句 &#xff09;Claude 3 Sonnet&#xff08;英文十四行诗&#xff09;Claude 3 Opus&#xff08;古典乐作品集…

docker-compose Install rustdesk

RustDesk RustDesk 是一款开源的远程支持和远程桌面工具,它旨在为用户提供便捷的远程协助和远程访问功能。 默认情况下,hbbs 监听21115(tcp), 21116(tcp/udp), 21118(tcp),hbbr 监听21117(tcp), 21119(tcp)。务必在防火墙开启这几个端口, 请注意21116同时要开启TCP和UDP。…

streamlit初学-用streamlit实现云台控制界面

用streamlit实现云台控制界面 效果图PC上的效果手机上的效果 源码: 本文演示了,如何用streamlit做一个云台控制界面。功能包括:用户登录,事件的处理,图片的更新 版本信息: streamlit_authenticator: 下载链接streamlit : 1.31.1python: 3.11 修改点: streamlit_authenticato…

AndroidStudio安装Android模拟器AVD及遇到的问题解决

打开DeiviceManager 创建虚拟机 选个常规的1080*1920分辨率 这里就遇到一个报错&#xff1a; Android SDK is up to date. Running Android Emulator hypervisor driver installer [SC] ControlService 失败 1062: 服务尚未启动。 [SC] DeleteService 成功 [SC] 由于发生错误…

在线部署ubuntu20.04服务器,安装jdk、mysql、redis、nginx、minio

查看服务器版本为20.04 lsb_release -a服务器初始账号密码 sxd / 123456 首先,更改自身密码都输入123456 sudo passwd 创建最高权限root账号&#xff0c;密码为 123456 su root 更新源列表 sudo apt-get update 安装 openssh-server和vim&#xff0c;途中输入y sudo ap…

Python爬虫:设置随机 User-Agent

Python爬虫&#xff1a;设置随机 User-Agent 在Python中编写爬虫时&#xff0c;为了模拟真实用户的行为并防止被服务器识别为爬虫&#xff0c;通常需要设置随机的User-Agent。你可以使用fake-useragent库来实现这一功能。首先&#xff0c;你需要安装fake-useragent库&#xff…

通过Apple Configurator 2导出iOS ipa包

通过Apple Configurator 2导出iOS ipa包 安装Apple Configurator 2 从Mac AppStore安装Apple Configurator 2 下载ipa 准备工作&#xff1a; 1、 电脑已经安装了Apple Configurator 2 2、 手机已经安装了目标软件 3、 Apple 账号已经下载过目标软件 打开后连接设备&#xf…

如何快速分析OB集群日志,敏捷诊断工具obdiag分析能力实践——《OceanBase诊断系列》之四

1. 前言 obdiag是OceanBase的敏捷诊断工具。1.2版本中&#xff0c;obdiag支持快速收集诊断信息&#xff0c;但仅有收集能力是不够的&#xff0c;还需要有分析能力。因此在obdiag的1.3.0版本中&#xff0c;我们加入了OB集群的日志分析功能。用户可以一键进行集群的OB日志的分析…

Redis核心数据结构之SDS(二)

SDS与C字符串的区别 杜绝缓冲区溢出 除了获取字符串长度的复杂度高之外&#xff0c;C字符串不记录自身长度带来的另一个问题是 容易造成缓冲区溢出(buffer overflow).例如<string.h>/strcat函数可以将src字符串 中的内容拼接到dest字符串的末尾: char *strcat(char *d…

c++中多种类型sort()排序的用法(数组、结构体、pair、vector)

c中多种类型sort排序的用法 一、对数组排序1、默认排序2、自定义排序 二、对结构体进行排序三、对pair进行排序1、默认排序2、自定义排序 四、对vector进行排序1、默认排序2、去重排序3、自定义排序 一、对数组排序 1、默认排序 默认从小到大进行排序 #include <bits/std…

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:拖拽控制)

设置组件是否可以响应拖拽事件。 说明&#xff1a; 从API Version 10开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 ArkUI框架对以下组件实现了默认的拖拽能力&#xff0c;支持对数据的拖出或拖入响应&#xff0c;开发者只需要将这些组件…

Xcode 15 适配 MonkeyDev

升级到Xcode15后,使用Xcode创建MonkeyApp后,运行会报错,本篇文章主要讲述此过程遇到的错误和解决办法。 问题1:找不到libc++.dylib文件 问题描述: Build input files cannot be found: /usr/lib/libstdc++.dylib, /usr/lib/libc++.dylib. Did you forget to declare th…

DHCP自动获取IP地址实验(华为)

思科设备参考&#xff1a;DHCP自动获取IP地址实验&#xff08;思科&#xff09; 一&#xff0c;实验目的 路由器搭载DHCP&#xff0c;让PC通过DHCP自动获取IP地址 二&#xff0c;不划分vlan--全局地址池 实验拓扑 配置命令 Router <Huawei>system-view [Huawei]ip po…

瑞_Redis_短信登录(一)

文章目录 项目介绍1 短信登录1.1 项目准备1.1.1 导入SQL1.1.2 导入后端项目1.1.3 导入前端项目 &#x1f64a; 前言&#xff1a;本文章为瑞_系列专栏之《Redis》的实战篇的短信登录章节的项目准备小节。由于博主是从B站黑马程序员的《Redis》学习其相关知识&#xff0c;所以本系…

LLM春招,搜广推,nlp(2)

Encoder和Decoder怎么交互的 decoder里面的K&#xff0c;V输入用的是encoder的输出&#xff0c;并不是共享了K, V参数&#xff0c;decoder每层的参数都是独立的。Decoder每层是有两块Attention的&#xff1a;一块是正常的Self-Attention&#xff0c;QKV的输入都来自Decoder上一…

docker单节点搭建在线商城

本文档使用到的软件包以上传到资源中 目录 1. 创建容器并配置基础内容 1.1 将gpmall-repo上传到容器中 1.2 添加yum源 2. 安装基础服务 2.1 安装JAVA环境 2.2 安装Redis缓存服务 2.3 安装Elasticsearch服务 2.4 安装Nginx服务 2.5 安装MariaDB数据库 2.6 安…

C++核心编程之内存分区模型,引用,函数提高

1&#xff0c;类型分区模型 c程序在执行中&#xff0c;将内存大方向划分为4个区域 1&#xff0c;代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理的 2&#xff0c;全局区&#xff1a;存放全局变量和静态变量以及常量 3&#xff0c;栈区&#xff1…

Spring框架的优点

Spring框架是一个开放源代码的J2EE应用程序框架&#xff0c;是针对bean的生命周期进行管理的轻量级容器。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题&#xff0c;提供了功能强大的IOC、AOP及Web MVC等功能。 轻量级&#xff1a;相对于EJB框架而言。 Spring 体系结…

Windows安装SSH教程

Windows安装SSH教程 一、SSH1.SSH简介2.SSH功能3.SSH验证3.1 第一种级别&#xff08;基于口令的安全验证&#xff09;3.2 第二种级别&#xff08;基于密匙的安全验证&#xff09; 4.SSH层次4.1 传输层协议 [SSH-TRANS]4.2 用户认证协议 [SSH-USERAUTH]4.3 连接协议 [SSH-CONNEC…

node-day3-es6模块化+webpack

模块化 一、模块化分类 回顾node.js模块化&#xff1a; node.js遵循了CommonJS的模块化规范【见下文】&#xff0c;其中&#xff1a; 1.导入其它模块使用require()方法 2.模块对外共享成员使用module.exports对象 模块化的好处&#xff1a; 大家都遵守同样的模块化规范写代…