基于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基础语法之后,就针对性的学习这个小项目所需要用到的知识点。每当需要实现一个功能的时候,就去学习对应章节的知识,用小项目驱动整个学习过程。理论和实践同时开展的效果就是,对这些知识你会有更深的理解。

相关推荐
xiaoopin3 小时前
简单的分布式锁 SpringBoot Redisson‌
spring boot·分布式·后端
青鱼入云3 小时前
redisson介绍
redis·1024程序员节
哲Zheᗜe༘7 小时前
了解学习Redis主从复制
数据库·redis·学习
一条懒鱼6668 小时前
Redis Sentinel哨兵集群
数据库·redis·sentinel
l1t9 小时前
Lua与LuaJIT的安装与使用
算法·junit·单元测试·lua·luajit
想ai抽9 小时前
pulsar与kafka的架构原理异同点
分布式·架构·kafka
千里镜宵烛9 小时前
Lua-迭代器
开发语言·junit·lua
Zhu_S W10 小时前
Redis跳表:高效有序数据结构的深度剖析
数据结构·数据库·redis
初学者_xuan12 小时前
零基础新手小白快速了解掌握服务集群与自动化运维(十五)Redis模块-哨兵集群
运维·redis·自动化
异构算力老群群12 小时前
纠删码(erasure coding,EC)技术现状
分布式·纠删码·lrc