当前位置: 首页 > news >正文

redis+lua+固定窗口实现分布式限流

用key的过期时间替代固定窗口的时间戳

-- KEYS[1]: 限流的key
-- ARGV[1]: 限流窗口大小(秒)
-- ARGV[2]: 限流阈值local key = KEYS[1]
local window = tonumber(ARGV[1])
local limit = tonumber(ARGV[2])-- 尝试获取当前计数
local current = redis.call("GET", key)if current == false then-- key不存在,初始化计数器并设置过期时间redis.call("SET", key, 1, "EX", window)return 1
else-- key存在,检查是否超过限制if tonumber(current) < limit thenredis.call("INCR", key)return 1elsereturn 0end
end

java客户端

public class FixedWindowRateLimiterWithTTL {private Jedis jedis;private String key;private int window; // 窗口大小(秒)private int limit;  // 限流阈值private static final String LUA_SCRIPT ="local key = KEYS[1]\n" +"local window = tonumber(ARGV[1])\n" +"local limit = tonumber(ARGV[2])\n" +"local current = redis.call(\"GET\", key)\n" +"if current == false then\n" +"    redis.call(\"SET\", key, 1, \"EX\", window)\n" +"    return 1\n" +"else\n" +"    if tonumber(current) < limit then\n" +"        redis.call(\"INCR\", key)\n" +"        return 1\n" +"    else\n" +"        return 0\n" +"    end\n" +"end";public FixedWindowRateLimiterWithTTL(Jedis jedis, String key, int window, int limit) {this.jedis = jedis;this.key = key;this.window = window;this.limit = limit;}public boolean allowRequest() {Object result = jedis.eval(LUA_SCRIPT, Collections.singletonList(key),Arrays.asList(String.valueOf(window),String.valueOf(limit)));return "1".equals(result.toString());}
}

使用

public static void main(String[] args) {Jedis jedis = new Jedis("localhost");// 创建一个每分钟最多100次请求的限流器FixedWindowRateLimiterWithTTL limiter = new FixedWindowRateLimiterWithTTL(jedis, "api:limit:user1", 60, 100);for (int i = 0; i < 120; i++) {if (limiter.allowRequest()) {System.out.println("处理请求 " + i);} else {System.out.println("限流请求 " + i);}}jedis.close();
}

优点:实现简单
缺点:
固定窗口算法无法解决临界问题
Redis的过期机制是惰性删除+定期删除,可能导致key实际过期时间与预期有微小差异
重启导致的窗口重置
在超高并发下会成为单点瓶颈

相关文章:

  • AcWing 885:求组合数 I ← 杨辉三角
  • seaborn数据统计可视化-介绍
  • 业绩回暖、股价承压,三只松鼠赴港上市能否重构价值锚点?
  • 道可云人工智能每日资讯|“人工智能科技体验展”在中国科学技术馆举行
  • GTC2025全球流量大会:领驭科技以AI云端之力,助力中国企业出海破浪前行
  • SECS-I vs HSMS-SS vs HSMS-GS 通信控制对比明细表
  • 可编程控制器应用
  • 《Go 语言高并发爬虫开发:淘宝商品 API 实时采集与 ETL 数据处理管道》
  • jenkins容器提示磁盘空间过低
  • 记一次pdf转Word的技术经历
  • pdf.js移动端预览PDF文件时,支持双指缩放
  • EasyCVR视频汇聚平台助力大型生产监控项目摄像机选型与应用
  • 多模态大型模型,实现以人为中心的精细视频理解
  • Golang|分布式索引架构
  • Go 语言入门:(一) 环境安装
  • uniapp 微信小程序遇到的坑
  • 8.Three.js中的 StereoCamera 立体相机详解+示例代码
  • 鼠标获取坐标 vs 相机获取坐标
  • Vue 2 和 Vue 3 中 Vue 实例变量方法的功能差异对比,包含关键方法的详细说明和表格总结
  • 网工备考考纲变化总结
  • 【社论】优化限购限行,激发汽车消费潜能
  • 外交部:对伊朗拉贾伊港口爆炸事件遇难者表示深切哀悼
  • 影子调查|23岁男子驾照拟注销背后的“被精神病”疑云
  • 国内生产、境外“游一圈”再进保税仓,这些“全球购”保健品竟是假进口
  • 比亚迪一季度日赚亿元,净利润同比翻倍至91.55亿元
  • 30天内三访中国,宝马董事长:没有一家公司可以在全球价值链外独立运行