为了账号安全,请及时绑定邮箱和手机立即绑定

基于Redis+Lua的分布式限流

标签:
Java

大家好,我是姚半仙,慕课网《Java架构师成长直通车》课程架构师讲师团成员之一。在本篇文章中我将带大家一起学习一个稍微复杂一点的分布式限流手段,利用Redis+Lua实现服务端限流。

架构思考:Why Redis?

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

![IPing](2.png)

  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年)甚至比JDK 1.0还要早。Lua是由标准的C语言编写的,它的源码部分不过2万多行C代码,甚至一个完整的Lua解释器也就200k的大小。

Lua往大了说是一个新的编程语言,往小了说就是一个脚本语言。对于有编程经验的同学,拿到一个Lua脚本大体上就能把业务逻辑猜的八九不离十了。我非常不建议同学们花大工夫去学习Lua的技术细节,Lua就像Shell脚本一样,尽管简单,但是细节之处还是相当繁琐的。

在分布式限流的章节中,我们以理解架构模式为主,大家只要明白为什么我们使用Lua和Redis,这样做有什么架构上的考量,这就足够了。在稍后的小节里,通过下面三个环节,带大家去理解Redis + Lua的分布式限流方案:

  1. Lua的基本用法和介绍,有哪些优点
  2. Lua脚本如何嵌入Redis中执行
  3. 开发一个基于Redis + Lua的限流工具,在业务层通过自定义注解的形式为方法提供限流功能

小结

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

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

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


更多精彩内容尽在《Java架构师成长直通车》

点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消