当前位置:网站首页>redis + lua实现分布式接口限流实现方案
redis + lua实现分布式接口限流实现方案
2022-06-24 20:01:00 【步尔斯特】
前言
redis + lua脚本已然成为了单体项目主流的限流方案。
redis凭借其特性成为了中间件的佼佼者,最新官方测试数据:
- 读的速度是110000次/s
- 写的速度是81000次/s。
lua:
- 减少网络开销:使用Lua脚本,无需向Redis 发送多次请求,执行一次即可,减少网络传输
- 原子操作:Redis 将整个Lua脚本作为一个命令执行,原子,无需担心并发
- 复用:Lua脚本一旦执行,会永久保存 Redis 中,,其他客户端可复用
操作
在需要限流的接口处添加如下注解(@RedisLimit),在原有基础上,无需添加任何依赖即可实现限流。
@RedisLimit(name = "订单秒杀", prefix = "seckill", key = "distributed", count = 1, period = 1, limitType = LimitType.IP, msg = "当前排队人数较多,请稍后再试!")
@GetMapping("/limit/distributed/{id}")
public ResponseEntity<Object> limitDistributed(@PathVariable("id") String id) {
return ResponseEntity.ok("成功购买:" + id + "个");
}
介绍
/** * 资源名称 */
String name() default "";
/** * 前缀 */
String prefix() default "";
/** * 资源key */
String key() default "";
/** * 最多访问次数 */
int count();
/** * 时间,秒级 */
int period();
/** * 类型 */
LimitType limitType() default LimitType.CUSTOMER;
/** * 提示信息 */
String msg() default "系统繁忙,请稍后再试";
功能
- 默认根据全局接口的QPS作为流控指标
- 可在独立IP和全局接口自由切换
- 可自定义时间及规定时间内的QPS
- 可根据key值做后期的数据监控和统计
原理
以流量作为切点、滑动时间窗口作为核心算法。
lua脚本以保证其原子性操作
核心代码(部分展示)
lua脚本
redis.replicate_commands();
local listLen,time
listLen = redis.call('LLEN', KEYS[1])
if listLen and tonumber(listLen) < tonumber(ARGV[1]) then
local a = redis.call('TIME');
redis.call('LPUSH', KEYS[1], a[1]*1000000+a[2])
else
time = redis.call('LINDEX', KEYS[1], -1)
local a = redis.call('TIME');
if a[1]*1000000+a[2] - time < tonumber(ARGV[2])*1000000 then
return 0;
else
redis.call('LPUSH', KEYS[1], a[1]*1000000+a[2])
redis.call('LTRIM', KEYS[1], 0, tonumber(ARGV[1])-1)
end
end
return 1;
切点处理
Long number = redisTemplate.execute(SECKILL_SCRIPT, keys, count, period);
if(number != null && number.intValue() == 1){
return pjp.proceed();
}
边栏推荐
- Working principle analysis of kubernetes architecture core components
- Several ways for wechat applet to jump to the page are worth collecting
- After 5 years of software testing in didi and ByteDance, it's too real
- Unmanned driving: Some Thoughts on multi-sensor fusion
- Qiniu cloud uploads video to get the first frame of video
- Difficult and miscellaneous problems: A Study on the phenomenon of text fuzziness caused by transform
- The drawableleft of the custom textview in kotlin is displayed in the center together with the text
- How to use promise Race() and promise any() ?
- Use and click of multitypeadapter in recycleview
- 传输层 以字节为单位的滑动窗口技术
猜你喜欢
Time unified system
Use of JMeter
[interview question] what is a transaction? What are dirty reads, unrepeatable reads, phantom reads, and how to deal with several transaction isolation levels of MySQL
Go crawler framework -colly actual combat (4) -- Zhihu answer crawl (2) -- visual word cloud
Alternative to log4j
Kubernetes 架构核心组件工作原理解析
C# Winform 最大化遮挡任务栏和全屏显示问题
2019 summary and 2020 outlook
On the difficulty of developing large im instant messaging system
iNFTnews | 国内NFT发展仅限于数字藏品吗?
随机推荐
ros(25):rqt_image_view报错Unable to load plugin for transport ‘compressed‘, error string
Ansible及playbook的相关操作
Go crawler framework -colly actual combat (IV) -- Zhihu answer crawl (I)
Use coordinatorlayout+appbarlayout+collapsingtoolbarlayout to create a collapsed status bar
Unmanned driving: Some Thoughts on multi-sensor fusion
水库大坝安全监测
Human body transformation vs digital Avatar
D omit parameter name
Design and practice of vivo server monitoring architecture
【面试题】什么是事务,什么是脏读、不可重复读、幻读,以及MySQL的几种事务隔离级别的应对方法
Go crawler framework -colly actual combat (4) -- Zhihu answer crawl (2) -- visual word cloud
断言(assert)的用法
C WinForm maximizes occlusion of the taskbar and full screen display
ServerSocket and socket connection
Wx applet jump page
The problem of multiple callback of video ads stimulated by applets (offcolse problem)
打卡smart精灵#1,品牌不缺吸引力,产品本身实力如何?
Related operations of ansible and Playbook
Dynamic effect of canvas lines
Current situation and development prospect forecast report of global and Chinese tetrahydrofurfuryl alcohol acetate industry from 2022 to 2028