基于Redis+Lua的分布式限流

本文已收录至我的个人网站:程序员波特,主要记录Java相关技术系列教程,共享电子书、Java学习路线、视频教程、简历模板和面试题等学习资源,让想要学习的你,不再迷茫。

前面我们了解了如何利用Nginx做网关层限流,这一小节我们学习

个稍微复杂一 点的分布式限流手段,利用Redis+Lua实现服务端限流,

架构思考: Why Redis

同学们一定有个疑问,这么多中间件,为什么我们选择用Redis。这就好比孙悟空选兵器,十八般兵器都不得心应手,唯有那东海龙宫的定海神针是最佳选择。

  1. 性能前面的章节中大家已经系统学习了Redis, 作为缓存组件,如果不采用持久化方案的话,Redis的大部分操作都是纯内存操作,性能十分优异
  2. 线程安全只用单线程承接网络请求(其他模块仍然多线程),天然具有线程安全的特性,而且对原子性操作的支持非常到位

限流服务不仅需要承接超高QPS,还需要保证限流逻辑的执行层面具备线程安全的特性。利用Redis的这些天然特性做限流,既能保证线程安全,也能保持良好的性能。

基于Redis限流的架构模式

我们先来设想下Redis限流的工作模式,在-个限流场景中通常主要有三个角色:

  1. 限流请求需要被限流的对象
  2. 限流规则定义一段程序或者脚本,当请求到来的时候执行
  3. 存储介质用来存储限流信息的地方,比如令牌个数或者是访问请求的计数

思考题 在上面这个流程中,有一个需要大家思考的问题,那就是"限流逻辑"这块应该放到哪个地方。是放到服务入口里执行?还是放到Redis里执行?

我们假定这个服务入口就是我们的Java程序,在Java中执行一段限流逻辑并不会带来多大的性能压力,但是!我们有没有考虑过Redis的感受?在一个限流逻辑里,我们往往需要发起多个Redis查询和修改指令,比如获取令牌这样一步,这里面就涉及到查询令牌、发放令牌等等步骤,这些步骤会发起多个Redis的请求指令,造成更多的网络开销。不光如此,我们还要保证这些操作是线程安全的,如此一来,在程序中就会涉及到资源锁定等复杂操作。

那我们有没有一个更好的方案来规避这些问题呢?答案是肯定的,我们可以做这么一个假设,有这么一种脚本,它可以嵌入到Redis中去,那么对我们的系统来说就不用在一次限流控制中发送多次Redis访问命令,减少了大量不必要的网络开销,减轻了Redis的压力。让我们进一步YY一下,假如Redis在执行这个脚本逻辑的过程中,是当做一个原子操作来做的,也就是说,脚本开始到结束的时间段内Redis都只盯着这个脚本执行,不会插入其他的命令,那岂不是线程安全的问题也解决了?放眼天下,可有此等脚本语言的存在?!

有!今天正好有一款产品,不要钱免费送(开源),你没听错,只要998,Lua脚本语言搬回家!

Lua脚本

Lua是一个很小巧精致的语言,它的诞生(1993年)甚至比JDK1.0还要早。Lua是由标准的C语言编写的,它的源码部分不过2万多行C代码,甚至一个完整的Lua解释器也就200k的大小。

Lua往大了说是一个新的编程语言,往小了说就是一个脚本语言。对于有编程经验的同学,拿到一个Lua脚本大体上就能把业务逻辑猜的八九不离十了。我非常不建议同学们花大工夫去学习Lua的技术细节,Lua就像Shell脚本一样,尽管简单,但是细节之处还是相当繁琐的。大家只要明白为什么我们使用Lua和Redis,这样做有什么架构上的考量,这就足够了。

小结

这一节我们了解了Redis+Lua限流方案的大致背景,接下来我们循序渐进,先从Lua开始讲起,一步步实现整个限流方案。

学习Tips: 大家在学习一门技术的时候要有主线和支线之分,且听我讲个故事。当我还在读书的时候,我周围很多同学是这样学技术的,买一本比砖头还厚的书(在十多年前纸质书籍还是主流),从第一页开始像推土机一样往后看,一个细节都不放过。事无巨细并不是一种好的学习方法,这就像很多女生喜欢用五颜六色的荧光笔在课本上划重点,划来划去一本书全部都是重点。这样学习效率高吗?我想未必!

我认为在学习中应该有明确的目标,跟着主线剧情走。从我自己来说,我在17年左右接触Java,在学习Java之初我的目标就是做一个桌面版的坦克大战游戏,这个小游戏就是我的学习主线。在了解了Java基础语法之后,就针对性的学习这个小项目所需要用到的知识点。每当需要实现一个功能的时候,就去学习对应章节的知识,用小项目驱动整个学习过程。理论和实践同时开展的效果就是,对这些知识你会有更深的理解。

相关推荐
xufengzhu14 小时前
第三方 Python 库 redis-py + hiredis 的使用
开发语言·redis·python
轻刀快马16 小时前
跨越软硬件的共鸣(二):从 Cache 写策略看 Redis 与 DB 的一致性博弈
java·开发语言·redis·计算机组成原理
ACP广源盛1392462567318 小时前
GSV5600@ACP#多接口协议转换芯片,物理 AI 便携终端的互联核心
大数据·人工智能·分布式·嵌入式硬件·spark
lazy H18 小时前
Spring Boot 项目如何连接 Redis?新手入门配置和常见错误总结
ide·spring boot·redis·后端·学习·intellij-idea
木雷坞19 小时前
Firecrawl Docker Compose 自托管排查:镜像、Redis、队列和 Playwright
redis·docker·容器·firecrawl
柏舟飞流20 小时前
Spring Boot 进阶实战:整合 MyBatis、Redis、JWT,搭一个更像真实项目的后端服务
spring boot·redis·mybatis
南部余额21 小时前
Canal解决MySQL与Redis数据一致性问题
数据库·redis·mysql·canal·数据·数据同步
典学长编程1 天前
Redis分布式缓存超详细教学(微服务版)!
redis·微服务·持久化·主从复制·redis哨兵集群
极客先躯1 天前
高级java每日一道面试题-2026年02月12日-实战篇[Docker]-什么是容器的 Seccomp 配置?如何自定义?
java·运维·分布式·docker·容器·自动化·文件
Francek Chen1 天前
【大数据处理与分析】MapReduce:06 MapReduce编程实践
大数据·hadoop·分布式·mapreduce