【Redis】分布式限流与Redis实现限流的四种方式(Redis专栏启动)

news2024/11/21 0:21:57

 

📫作者简介:小明java问道之路,专注于研究 Java/ Liunx内核/ C++及汇编/计算机底层原理/源码,就职于大型金融公司后端高级工程师,擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。

        

📫 热衷分享,喜欢原创~ 关注我会给你带来一些不一样的认知和成长。

        

🏆 CSDN博客专家/后端领域优质创作者/内容合伙人、InfoQ签约作者、阿里云专家/签约博主、51CTO专家 🏆

        

🔥如果此文还不错的话,还请👍关注、点赞、收藏三连支持👍一下博主~ 


专栏系列(点击解锁)

学习路线(点击解锁)

知识定位

🔥MySQL从入门到精通🔥

MySQL从入门到精通

全面讲解MySQL知识与实战

🔥计算机底层原理🔥

深入理解计算机系统CSAPP

构件计算机体系和计算机思维

Linux内核源码解析

围绕Linux内核讲解计算机底层原理与并发

🔥数据结构与企业题库精讲🔥

数据结构与企业题库精讲

结合工作经验深入浅出,适合各层次,笔试面试算法题精讲

🔥互联网架构分析与实战🔥

企业系统架构分析实践与落地

行业前沿视角,专注于技术架构升级路线、架构实践

互联网企业防资损实践

金融公司的防资损方法论、代码与实践。

本文目录

本文目录

本文导读

一、什么是分布式限流

二、基于Redis的setnx操作

三、基于Redis的数据结构zset

三、Redis + Lua脚本实现限流

四、基于Redis的List数据结构实现令牌桶算法

总结


本文导读

本文介绍分布式系统和分布式限流,我们现在的生产中的限流包括网关层的限流与Redis实现的限流策略,主要有基于Redis的 setnx 操作、List、zset实现的滑动窗口,以及Redis的Lua脚本实现分布式限流。

一、什么是分布式限流

分布式系统必须是由多个节点组成的系统,其中节点是指计算机服务器,这些节点一般不是孤立的,而是相互连接的,这些连接的节点部署我们的节点,它们的操作将得到协调。

不同的业务模块部署在不同的服务器上,或者同一业务模块拆分多个子业务并将其部署在不同服务器上,以解决高并发性问题,并提供可扩展性和高可用性。

分布式限流的原理很简单,一言以蔽之,分布式与单机流量限制场景不同,它将整个分布式环境中的所有服务器视为一个整体。

例如对于IP流限制,假设,我们限制一个IP每秒最多1000次访问。

无论来自该IP的请求落在哪台计算机上,只要它访问集群中的服务节点,它都将受到流限制规则的约束。

从上面的示例中很容易看出,我们必须将流量限制信息保存在“集中式”组件上,这样它才能获得集群中所有机器的访问状态。

目前主流的限流方案有两种:

1、网关层(Nginx、Openresty、Spring Cloud Gateway等)流量限制将流量限制规则应用于所有交通入口

(在Nginx中 ngx_http_limit_req_module 模块限制访问频率,nginx.conf配置文件中可以使用limit_req_zone命令及limit_req命令限制请求速率;限制请求速率)。

2、中间件限流,将流限制信息存储在分布式环境中的中间件中(如Redis),每个组件可以从中获取当前时间的流量统计信息,从而决定是拒绝服务还是释放流量。

二、基于Redis的setnx操作

当我们使用Redis分布式锁时,依赖于setnx指令。

流量限制的主要目的是在单位时间内只允许N个请求访问我的代码程序。因此,依靠setnx可以轻松实现此功能。

例如,如果我们需要在1秒内限制1000个请求,我们可以在设置setnx时将过期时间设置为1000。当setnx请求数达到20个时,就达到了流量限制效果,代码相对简单。

当然,这种方法有很多缺点。例如,当我们计数1-10秒时,我们不能在2-11秒内计数。如果我们需要在N秒内计数M个请求,我们需要在Redis中保留N个密钥。

三、基于Redis的数据结构zset

限制中最重要算法之一就是的是滑动窗口,可以解决上述,提到了1-10如何变成2-11的缺陷。zset起始值和结束值都+1即可。

我们可以将请求放入 zset 数组中,当请求进入时,该 value 保持唯一。它可以实现滑动窗口的效果,并且可以保证每N秒最多M个请求。缺点是zset的数据结构会越来越大。实现方法相对简单。

原理是获取一段时间的 size 值,如果这个 size 大于我们设定的一个值,例如1000,则return失败,小于则把这个请求放入 zset 中。

// intervalTime是限流的时间
Integer count = redisTemplate.opsForZSet()
    .rangeByScore("limit", currentTime -  intervalTime, currentTime).size();

// 把这个请求放入 zset 中
redisTemplate.opsForZSet()
    .add("limit",UUID.randomUUID().toString(), currentTime);

三、Redis + Lua脚本实现限流

分布式流量限制的关键是使流量限制服务全局化。Redis+Lua脚本可用于实现高并发和高性能的流量限制。

Lua是一种轻量级、紧凑的脚本语言,用标准C语言编写,嵌入在应用程序,为应用程序提供灵活的扩展和定制功能。

-- 获取调用脚本时传入的第一个key值(用作限流的 key)
local key = KEYS[1]
-- 获取调用脚本时传入的第一个参数值(限流大小)
local limit = tonumber(ARGV[1])

-- 获取当前流量大小
-- (redis.call方法,从缓存中get和key相关的值,如果为null那么就返回0)
local curentLimit = tonumber(redis.call('get', key) or "0")

-- 判断缓存中记录的数值是否会大于限制大小,如果超出表示该被限流,返回0
-- 如果未超过,那么该key的缓存值+1,并设置过期时间,并返回缓存值+1

-- 是否超出限流(如果超出限流大小,直接返回)
if curentLimit + 1 > limit then
    return 0
else
    redis.call("INCRBY", key, 1) -- 没有超出 value + 1(请求数+1)
    redis.call("EXPIRE", key, 2) -- 设置过期时间(设置2秒过期)
    return 1 -- 放行请求
end

好处:减少网络开销,使用Lua脚本,不需要向Redis发送多个请求,只需执行一次,并减少网络传输;Redis将整个Lua脚本作为命令执行是原子操作,无需担心并发问题;一旦Lua脚本被执行,它将被永久保存在Redis中,并且可以被其他客户端重用。

四、基于Redis的List数据结构实现令牌桶算法

令牌桶算法指的是输入速率和输出速率。当输出速率大于输入速率时,超过流量限制。也就是说,我们每次访问请求时都可以从Redis获取令牌。如果我们得到一个令牌,这意味着没有超过限制。如果我们不能获得令牌,结果是相反的。

也就是说令牌桶算法的原理是系统将以恒定的速度将令牌放入桶中,需要则获取令牌。当存储桶中没有可用令牌时,则将被拒绝。

基于以上思想,Redis的List、zset等数据结构都可以实现。

// 获取令牌,返回 null 代表当前令牌桶中无令牌,则拒绝请求
Object result = redisTemplate.opsForList().leftPop("limit_list");


// 在令牌桶中添加令牌(令牌需要唯一)
redisTemplate.opsForList()
	.rightPush("limit_list",UUID.randomUUID().toString());

总结

本文介绍分布式系统和分布式限流,我们现在的生产中的限流包括网关层的限流与Redis实现的限流策略,主要有基于Redis的 setnx 操作、List、zset实现的滑动窗口,以及Redis的Lua脚本实现分布式限流。

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

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

相关文章

MHA高可用及故障切换

目录 一、MHA的概述 1、 MHA的概念 2.MHA 的组成 3.MHA 的特点 二、搭建 MySQL MHA的操作步骤 1、实验思路: 1.1、MHA架构 1.2、故障模拟 2、环境准备 3、修改 Master、Slave1、Slave2 节点的主机名 4、修改 Master、Slave1、Slav…

基于java+springboot+mybatis+vue+mysql的农产品销售商城网站

项目介绍 农产品销售成为了很多农产品商家的一项重要的创收项目。传统的销售方式采用了摆摊销售和市场的农产品的批发,在销售农产品方面不是很方便,因此采用了网络的方式进行销售。也是电子商务发展今天的一种趋势,建立了网站,前…

WebSocket——SpringBoot+Vue3+TS+SockJS+STOMP简单连接使用

WebSocket——SpringBootVue3TSSockJSSTOMP简单连接使用本文视频以及相关资源关于WebSocket文档什么时候使用WebSocketWebSocket连接头服务器返回状态码客户端使用技术Github地址npm安装为什么要安装sockjs的.d.ts文件常用方法1.连接2.关闭连接3.发送消息4.设置订阅构建1.创建w…

【Redis】Redis布隆过滤器工作原理与实战(Redis专栏启动)

📫作者简介:小明java问道之路,专注于研究 Java/ Liunx内核/ C及汇编/计算机底层原理/源码,就职于大型金融公司后端高级工程师,擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。 &#x1…

判断质数复习与分解质因数

TIPS 1. 之前我们讲到比方说要得到一个整数(十进制形式)的每一位数字,就需要把这个整数先%10得到最低位的数字,然后呢再把这个整数/10更新一下,然后呢就这么循环往复直到最终这个不断更新的整数为0跳出循环。那如果这…

深度学习-神经网络(Pytorch应用)

文章目录简介卷积层池化层激活层线性层前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 上图摘自网络 受生物神经网络的启发,每个神经元与其他神经元相连,当…

InfluxDB时序数据库-笔记-更新中

本笔记由在Bilibili学习的尚硅谷教学视频后整理得来 文章目录一、InfluxDB基础概念1.1InfluxDB是什么1.2为什么选择InfluxDB而不选择关系型数据库1.3下载安装1.4Promethus数据格式1.5时序数据中的数据模型1.6与时间标准相关的知识二、Flux语言2.1初识Flux语言2.2Flux基本语法三…

献上SpringBoot核心笔记,简直就是血赚

市面上真正适合学习的SpringBoot资料太少,有的书或资料虽然讲得比较深入,但是语言晦涩难懂,大多数人看完这些书基本都是从入门到放弃。学透SpringBoot难道就真的就没有一种适合大多数同学的方法吗? 很多SpringBoot相关的知识点与…

Java+MySQL学生选课与成绩管理系统(数据库版)

一、项目要求 学生选课与成绩管理系统(数据库版) 1、配置MySQL数据库 2、利用java+MySQL实现系统各个功能 3、功能包括: (1)系统交互界面,如下图所示 (2)学生信息的增删改查。学生属性包括学号(唯一),姓名,专业。 (3)课程信息的增删改查。课程属性包括编号…

96-114-mysql-高级篇-架构篇

96-mysql-高级篇: 推荐网站 mysql学习网站:https://www.bilibili.com/video/BV1iq4y1u7vj?p109&vd_source39a1ba1654411bc9ab90f6f2926600b7 mysql:https://dev.mysql.com/doc/refman/8.0/en/ 算法:https://www.cs.usfca.…

JoyStick Shield连接Nokia 5110--Arduino

SpaceTrash游戏是一个简单的射击游戏,您可以在其中控制宇宙飞船,并通过移动或爆破(使用激光)来避免漂浮在周围的小行星的碰撞。该游戏是u8g2图形库附带的示例,该图形库通常用于连接具有SPI或I2C协议的各种单色8位显示器…

非零基础自学Golang 第1章 走进Go 1.4 常用软件及网站 1.5 小结

非零基础自学Golang 文章目录非零基础自学Golang第1章 走进Go1.4 常用软件及网站1.4.1 开发工具【IDE 或编辑器】1.4.2 代码管理工具1.4.3 其他工具1.4.4 网站资源1.5 小结第1章 走进Go 1.4 常用软件及网站 1.4.1 开发工具【IDE 或编辑器】 工欲善其事必先利其器。 Go开发工…

基于java+springboot+mybatis+vue+mysql的电动车辆充电桩管理系统

项目介绍 随着我国汽车行业的不断发展,电动汽车已经开始逐步的领导整个汽车行业,越来越多的人在追求环保和经济实惠的同时开始使用电动汽车,电动汽车和燃油汽车最大的而不同就是 需要充电,同时我国的基础充电桩也开始遍及了大多数…

机器人开发--SICK激光雷达系列

机器人开发--SICK激光雷达系列1 介绍2 TiM系列2.1 TiM510参数测量方法协议请求一次数据(应答直接携带数据)请求持续数据(应答收到指令,数据持续发送)数据内容参考1 介绍 SICK 是国际先进的工业用传感器应用程序解决方…

016 | 乡村振兴战略下农村宅基地有偿退出现状 | 大学生创新训练项目申请书 | 极致技术工厂

(一)研究目的 随着国家城市化进程的加快,城市和农村的具体情况都发生了巨大变化,大量的问题随之产生,在农村经济中,宅基地的有偿退出矛盾尤为突出。在当前的时代发展背景下,我国农村宅基地有偿…

[附源码]Python计算机毕业设计宠物寄养平台设计Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等…

git cherry-pick命令用法详解

1、需求背景 想在某个稳定版本上,添加一个刚开发完成的版本中的功能。就可以使用 Cherry-pick 命令,将这个功能相关的 commit 提取出来,合入稳定版本的分支上。 对于多分支的代码库,将代码从一个分支转移到另一个分支是常见需求。…

VS2015+PCL1.8.1安装

VS2015+PCL1.8.1安装 一、下载PCL1.8.1二、PCL-1.8.1安装三、系统环境变量配置四、 vs2015配置PCL1.8.1一、下载PCL1.8.1 1.1 首先下载pcl1.8.1的库,地址在这:pcl1.8.1库链接。   1.2 打开网站,将页面拉到最下面,下载这个两个文件:PCL-1.8.1-AllInOne-msvc2015-win64.ex…

Windows下C语言程序和网络调试助手通信

网络调试助手之间进行UDP通信 前面一篇文章介绍了Windows下的网络调试助手,文章链接如下: Windows下的TCP/UDP网络调试工具-NetAssist以及Linux下的nc网络调试工具 下面我们简单介绍一下网络调试助手的使用。 这样两个网络调试助手之间就可以进行UDP通…

矩阵 的逆、 迹、 秩

矩阵的逆: 矩阵的逆有是三种方法可以求 1、系数待定法: 2、求伴随矩阵求逆 3、通过求增广矩阵求出逆 矩阵的迹 什么是矩阵的迹 矩阵的迹是特征值的加和,也即矩阵A的主对角线元素的总和。 案例 矩阵的秩 什么是矩阵的秩 设 AA 为 m\tim…