当前位置:网站首页>redis + lua实现分布式接口限流实现方案

redis + lua实现分布式接口限流实现方案

2022-08-11 05:36:00 CSDN云计算

97b0036f4cf570c460567e229cc404e5.gif

作者 | 步尔斯特

来源 | 步尔斯特

前言

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();
            }

dcb933339e53e42bef747c4a46437b38.gif

往期推荐

一篇文章了解 Docker 的安装、启动以及工作原理!

剖析 kubernetes 集群内部 DNS 解析原理

Docker 镜像和容器的导入导出及常用命令

如何从 Docker 镜像里提取 dockerfile!

c97ef7a38d18249044ca2f98160430e0.gif

点分享

be027d0d9763bfaa3b35730c7696b21f.gif

点收藏

696a8f41cfcd6e023326ca072cafad24.gif

点点赞

1f90725723055c3630018bd99d272314.gif

点在看

原网站

版权声明
本文为[CSDN云计算]所创,转载请带上原文链接,感谢
https://blog.csdn.net/FL63Zv9Zou86950w/article/details/126276898