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

Redis实现分布式限流的几种方法

使用Redis实现分布式限流是一种常见且有效的方法,可以防止系统过载并确保公平的资源分配。Redis的高性能和丰富的数据结构使其成为实现分布式限流的理想选择。常见的限流算法包括固定窗口计数、滑动窗口计数和令牌桶算法。

1. 固定窗口计数算法

固定窗口计数算法将时间划分为固定长度的窗口,并在每个窗口内计数请求的数量。

示例代码

以下示例展示了如何使用Redis实现固定窗口计数算法的分布式限流:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

importredis.clients.jedis.Jedis;

publicclassFixedWindowRateLimiter {

privateJedis jedis;

privateintmaxRequests;

privateintwindowSize;// 窗口大小,单位为秒

publicFixedWindowRateLimiter(String host,intport,intmaxRequests,intwindowSize) {

this.jedis =newJedis(host, port);

this.maxRequests = maxRequests;

this.windowSize = windowSize;

}

publicbooleanisAllowed(String clientId) {

String key ="rate_limiter:"+ clientId;

longcurrentWindow = System.currentTimeMillis() /1000/ windowSize;

String windowKey = key +":"+ currentWindow;

longrequestCount = jedis.incr(windowKey);

if(requestCount ==1) {

jedis.expire(windowKey, windowSize);

}

returnrequestCount <= maxRequests;

}

publicvoidclose() {

jedis.close();

}

publicstaticvoidmain(String[] args) {

FixedWindowRateLimiter rateLimiter =newFixedWindowRateLimiter("localhost",6379,5,60);

for(inti =0; i <10; i++) {

booleanallowed = rateLimiter.isAllowed("client1");

System.out.println("Request "+ (i +1) +" allowed: "+ allowed);

try{

Thread.sleep(500);// 模拟请求间隔

}catch(InterruptedException e) {

e.printStackTrace();

}

}

rateLimiter.close();

}

}

2. 滑动窗口计数算法

滑动窗口计数算法通过记录多个小窗口内的请求数,计算滑动窗口内的总请求数。

示例代码

以下示例展示了如何使用Redis实现滑动窗口计数算法的分布式限流:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

importredis.clients.jedis.Jedis;

importredis.clients.jedis.Transaction;

importjava.util.List;

publicclassSlidingWindowRateLimiter {

privateJedis jedis;

privateintmaxRequests;

privateintwindowSize;// 窗口大小,单位为秒

privateintinterval;// 时间间隔,单位为秒

publicSlidingWindowRateLimiter(String host,intport,intmaxRequests,intwindowSize,intinterval) {

this.jedis =newJedis(host, port);

this.maxRequests = maxRequests;

this.windowSize = windowSize;

this.interval = interval;

}

publicbooleanisAllowed(String clientId) {

String key ="rate_limiter:"+ clientId;

longcurrentTime = System.currentTimeMillis() /1000;

longwindowStart = currentTime - windowSize;

Transaction transaction = jedis.multi();

transaction.zadd(key, currentTime, String.valueOf(currentTime));

transaction.zremrangeByScore(key,0, windowStart);

transaction.zcard(key);

transaction.expire(key, windowSize + interval);

List<Object> results = transaction.exec();

longrequestCount = (long) results.get(2);

returnrequestCount <= maxRequests;

}

publicvoidclose() {

jedis.close();

}

publicstaticvoidmain(String[] args) {

SlidingWindowRateLimiter rateLimiter =newSlidingWindowRateLimiter("localhost",6379,5,60,1);

for(inti =0; i <10; i++) {

booleanallowed = rateLimiter.isAllowed("client1");

System.out.println("Request "+ (i +1) +" allowed: "+ allowed);

try{

Thread.sleep(500);// 模拟请求间隔

}catch(InterruptedException e) {

e.printStackTrace();

}

}

rateLimiter.close();

}

}

3. 令牌桶算法

令牌桶算法通过生成令牌来控制请求的速率。每次请求需要消耗一个令牌,如果桶中没有令牌,则请求被拒绝。

示例代码

以下示例展示了如何使用Redis实现令牌桶算法的分布式限流:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

importredis.clients.jedis.Jedis;

publicclassTokenBucketRateLimiter {

privateJedis jedis;

privateintmaxTokens;

privateintrefillRate;// 令牌生成速率,单位为令牌/秒

publicTokenBucketRateLimiter(String host,intport,intmaxTokens,intrefillRate) {

this.jedis =newJedis(host, port);

this.maxTokens = maxTokens;

this.refillRate = refillRate;

}

publicbooleanisAllowed(String clientId) {

String key ="rate_limiter:"+ clientId;

longcurrentTime = System.currentTimeMillis() /1000;

longlastRefillTime = jedis.hget(key,"lastRefillTime") ==null?

0: Long.parseLong(jedis.hget(key,"lastRefillTime"));

inttokens = jedis.hget(key,"tokens") ==null?

maxTokens : Integer.parseInt(jedis.hget(key,"tokens"));

longtokensToAdd = (currentTime - lastRefillTime) * refillRate;

tokens = Math.min(maxTokens, tokens + (int) tokensToAdd);

lastRefillTime = currentTime;

if(tokens >0) {

jedis.hset(key,"tokens", String.valueOf(tokens -1));

jedis.hset(key,"lastRefillTime", String.valueOf(lastRefillTime));

returntrue;

}else{

jedis.hset(key,"tokens", String.valueOf(tokens));

jedis.hset(key,"lastRefillTime", String.valueOf(lastRefillTime));

returnfalse;

}

}

publicvoidclose() {

jedis.close();

}

publicstaticvoidmain(String[] args) {

TokenBucketRateLimiter rateLimiter =newTokenBucketRateLimiter("localhost",6379,5,1);

for(inti =0; i <10; i++) {

booleanallowed = rateLimiter.isAllowed("client1");

System.out.println("Request "+ (i +1) +" allowed: "+ allowed);

try{

Thread.sleep(500);// 模拟请求间隔

}catch(InterruptedException e) {

e.printStackTrace();

}

}

rateLimiter.close();

}

}

4. 令牌桶算法与Lua脚本

为了确保限流操作的原子性,可以使用Redis的Lua脚本。以下示例展示了如何结合Lua脚本和令牌桶算法来实现分布式限流。

Lua脚本

保存为token_bucket.lua

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

local key = KEYS[1]

local maxTokens = tonumber(ARGV[1])

local refillRate = tonumber(ARGV[2])

local currentTime = tonumber(ARGV[3])

local tokens = tonumber(redis.call("hget", key, "tokens") or maxTokens)

local lastRefillTime = tonumber(redis.call("hget", key, "lastRefillTime") or 0)

local tokensToAdd = math.floor((currentTime - lastRefillTime) * refillRate)

tokens = math.min(maxTokens, tokens + tokensToAdd)

lastRefillTime = currentTime

if tokens > 0 then

redis.call("hset", key, "tokens", tokens - 1)

redis.call("hset", key, "lastRefillTime", lastRefillTime)

return 1

else

redis.call("hset", key, "tokens", tokens)

redis.call("hset", key, "lastRefillTime", lastRefillTime)

return 0

end

Java代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

importredis.clients.jedis.Jedis;

importredis.clients.jedis.JedisPool;

importjava.io.IOException;

importjava.nio.file.Files;

importjava.nio.file.Paths;

publicclassTokenBucketRateLimiterWithLua {

privateJedisPool jedisPool;

privateString luaScript;

privateString scriptSha;

publicTokenBucketRateLimiterWithLua(String host,intport, String scriptPath)throwsIOException {

this.jedisPool =newJedisPool(host, port);

this.luaScript =newString(Files.readAllBytes(Paths.get(scriptPath)));

try(Jedis jedis = jedisPool.getResource()) {

this.scriptSha = jedis.scriptLoad(luaScript);

}

}

publicbooleanisAllowed(String clientId,intmaxTokens,intrefillRate) {

String key ="rate_limiter:"+ clientId;

longcurrentTime = System.currentTimeMillis() /1000;

到此这篇关于Redis实现分布式限流的几种方法 的文章就介绍到这了,

http://www.jsqmd.com/news/657287/

相关文章:

  • LLM-Graph-Builder:基于大语言模型的智能知识图谱构建解决方案
  • 博弈论算法精讲:从公平组合游戏到SG函数实战(ACM/OI选手必备)
  • 交直流混合微电网架构:拓扑优化与功率交互设计
  • 2026年3月SMT精密激光钢网供应商推荐分析,精密激光切割加工/SMT纳米阶梯钢网,SMT精密激光钢网源头厂家推荐分析 - 品牌推荐师
  • SITS2026智能生成能力雷达图(11维评估):从TypeScript泛型推导到Spring Boot事务链路补全,谁真正读懂了你的代码语义?
  • Adobe-GenP 3.0:解密Adobe全家桶通用补丁的技术实现与应用指南
  • 康耐视VisionPro:从“固定”到“灵活”,工业标定的实战进阶指南
  • 谷歌调整“水手计划”团队,浏览器智能体遇冷,新模型效率提升 50 倍!
  • 蓝桥杯单片机备赛避坑指南:从第九届省赛代码里学到的3个调试技巧与1个常见误区
  • MinerU 系列教程 第十一课:表格识别 - 有线与无线的双引擎
  • 如何为Windows安卓子系统打造完整的Android体验:MagiskOnWSALocal终极指南
  • EC开发tips
  • VRC Gesture Manager:Unity编辑器中实时预览VRChat虚拟形象动画的终极工具
  • 用Python和MATLAB搞定CCA:从数据预处理到结果可视化的完整实战指南
  • 用51单片机红外遥控器控制LED亮度(PWM调光保姆级教程)
  • SCL语言实战:在西门子PLC中构建高效FIFO栈数据结构
  • 3个强力技巧:用BilibiliDown实现B站音频高效提取完全指南
  • 【WindowsClear】一款面向 Windows 系统盘的 C盘清理工具,支持AppDate一键迁移到别的磁盘
  • 快速排序与希尔排序实战解析
  • 智能代码生成从“能用”到“飞快”的临界点:基于Transformer Decoder注意力机制重构的4种轻量化生成策略(含可复现PyTorch代码片段)
  • 手机号查QQ号终极指南:3步快速查询完整教程
  • Zotero文献格式化插件终极指南:一键告别杂乱文献库的完整解决方案
  • DeepMosaics终极指南:3个简单步骤掌握AI智能马赛克处理技术
  • MinerU 系列教程 第十二课:公式识别 - LaTeX 的自动生成
  • AI编程工具使用详解
  • 一篇文章带你快速上手Vue3(包含vue核心语法、router路由、axios请求库、pinia状态管理、ts类型约束等等)
  • Excel公式美化器:终极免费工具,让复杂公式一目了然!
  • 【GitHub项目推荐--Agentic Design Patterns:AI Agent 架构设计的“中文版设计模式”】⭐⭐⭐⭐⭐
  • 如何快速将飞书文档转换为Markdown:终极解决方案指南
  • 中层已死,智能体在管你