当前位置:网站首页>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();
}
边栏推荐
- Binder mechanism and Aidl communication example
- [distributed system design profile (2)] kV raft
- Helm chart仓库操作
- Outer screen and widescreen wasted? Harmonyos folding screen design specification teaches you to use it
- Related operations of ansible and Playbook
- JMeter socket connection sends data
- Go crawler framework -colly actual combat (II) -- Douban top250 crawling
- [proteus simulation] example of using timer 0 as a 16 bit counter
- D does not require opapply() as a domain
- Intensive reading of thinking about markdown
猜你喜欢

Virtual machine - network configuration

部门新来的00后真是卷王,工作没两年,跳槽到我们公司起薪18K都快接近我了

Apk slimming compression experience

2019 summary and 2020 outlook

Apk decompiled method (not confused)

Ansible及playbook的相关操作

Ott marketing is booming. How should businesses invest?

【面试题】什么是事务,什么是脏读、不可重复读、幻读,以及MySQL的几种事务隔离级别的应对方法

C# Winform 最大化遮挡任务栏和全屏显示问题

Power application of 5g DTU wireless communication module
随机推荐
Apk slimming compression experience
How to quickly open traffic master for wechat applet
部门新来的00后真是卷王,工作没两年,跳槽到我们公司起薪18K都快接近我了
Hyperledger Fabric 2. X dynamic update smart contract
ros(25):rqt_image_view报错Unable to load plugin for transport ‘compressed‘, error string
D does not require opapply() as a domain
[leaderboard] Carla leaderboard leaderboard leaderboard operation and participation in hands-on teaching
技术分享| WVP+ZLMediaKit实现摄像头GB28181推流播放
[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
UE4 WebBrowser chart cannot display problems
Ott marketing is booming. How should businesses invest?
融合模型权限管理设计方案
Paper review: U2 net, u-net composed of u-net
Xcode预览(Preview)显示List视图内容的一个Bug及解决
Requests Library
Power application of 5g DTU wireless communication module
Dynamic effect of canvas lines
Qiniu cloud uploads video to get the first frame of video
C# 闭包的垃圾回收
Use of navigation and navigationui