使用Redis Lua脚本实现高级限流策略

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 使用Redis Lua脚本实现高级限流策略

引言

在现代的Web应用中,限流是一个非常重要的功能,它帮助我们控制对某些资源的访问频率,以防止系统过载和滥用。Redis是一个高性能的键值存储系统,它的原子操作和Lua脚本功能为实现复杂的限流策略提供了强大的支持。本文将详细介绍一个使用Redis Lua脚本实现的高级限流策略。

理解限流Lua脚本

Lua脚本是Redis中一种强大的功能,它可以在服务器端执行复杂的逻辑,而无需在客户端进行多次调用。这对于实现限流逻辑来说是非常有用的,因为它可以保证限流操作的原子性。

下面是一个用于限流的Lua脚本示例:

-- 获取KEY
local limitResourceKey = KEYS[1]
-- 限流时间窗口(毫秒)
local limitTimeWindowMillis = tonumber(ARGV[1])
-- 当前时间(毫秒)
local currentMillis = tonumber(ARGV[2])
-- 最大次数
local limitCount = tonumber(ARGV[3])

-- 窗口开始时间
local windowStartMs = currentMillis - limitTimeWindowMillis
-- 获取key的次数
local current = redis.call('zcount', limitResourceKey, windowStartMs, currentMillis)

-- 如果key的次数存在且大于预设值直接返回false
if current and tonumber(current) >= limitCount then
    return false
end

-- 清除所有过期成员
redis.call("ZREMRANGEBYSCORE", limitResourceKey, 0, windowStartMs)

-- 添加当前成员
math.randomseed(currentMillis)
local uniqueId = tostring(currentMillis) .. tostring(math.random(1000, 9999))
redis.call("zadd", limitResourceKey, currentMillis, uniqueId)
redis.call("expire", limitResourceKey, limitTimeWindowMillis / 1000)

-- 返回true表示操作成功,没有超出限流
return true


脚本解析

1. 获取参数

脚本首先获取三个参数:限流的键(limitResourceKey)、时间窗口大小

limitTimeWindowMillis)和当前时间(currentMillis)。此外,还有一个最大请求次数的参数(limitCount)。

2. 计算窗口开始时间

使用当前时间和时间窗口大小计算出窗口的开始时间(windowStartMs),这个时间用于确定计数的起始点。

3. 计数

使用zcount命令来获取在当前时间窗口内已经记录的请求次数。zcount是一个有序集合的命令,它可以用来获取指定分数区间的成员数量。

4. 检查是否超出限流

如果当前的请求次数加上即将到来的请求已经超过了设定的最大次数,则直接返回false,表示请求被限流。


5. 清除过期成员

使用ZREMRANGEBYSCORE命令来清除时间窗口之外的过期请求记录,确保有序集合中只包含当前时间窗口内的请求记录。

6. 添加当前请求

使用zadd命令添加当前请求的记录,同时使用math.random生成一个随机数来确保成员的唯一性。然后设置这个键的过期时间,以便自动清理。

7. 返回结果

如果脚本执行到这里,说明请求没有超出限流,返回true

使用场景

这个Lua脚本可以在多种场景中使用,例如API的限流、秒杀系统的请求控制等。通过将这个脚本集成到你的应用程序中,你可以有效地控制对关键资源的访问频率。

结语

通过使用Redis的Lua脚本功能,我们可以高效且安全地实现复杂的限流逻辑。这种方法不仅减少了网络延迟,还保证了限流操作的原子性,从而提高了系统的稳定性和可靠性。希望本文能够帮助你更好地理解和应用Redis Lua脚本来实现限流策略。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
目录
打赏
0
4
4
0
139
分享
相关文章
高并发秒杀系统实战(Redis+Lua分布式锁防超卖与库存扣减优化)
秒杀系统面临瞬时高并发、资源竞争和数据一致性挑战。传统方案如数据库锁或应用层锁存在性能瓶颈或分布式问题,而基于Redis的分布式锁与Lua脚本原子操作成为高效解决方案。通过Redis的`SETNX`实现分布式锁,结合Lua脚本完成库存扣减,确保操作原子性并大幅提升性能(QPS从120提升至8,200)。此外,分段库存策略、多级限流及服务降级机制进一步优化系统稳定性。最佳实践包括分层防控、黄金扣减法则与容灾设计,强调根据业务特性灵活组合技术手段以应对高并发场景。
733 7
【📕分布式锁通关指南 03】通过Lua脚本保证redis操作的原子性
本文介绍了如何通过Lua脚本在Redis中实现分布式锁的原子性操作,避免并发问题。首先讲解了Lua脚本的基本概念及其在Redis中的使用方法,包括通过`eval`指令执行Lua脚本和通过`script load`指令缓存脚本。接着详细展示了如何用Lua脚本实现加锁、解锁及可重入锁的功能,确保同一线程可以多次获取锁而不发生死锁。最后,通过代码示例演示了如何在实际业务中调用这些Lua脚本,确保锁操作的原子性和安全性。
346 6
【📕分布式锁通关指南 03】通过Lua脚本保证redis操作的原子性
Redis的数据淘汰策略有哪些 ?
Redis 提供 8 种数据淘汰策略: 淘汰易失数据(具有过期时间的数据) 1. volatile-lru(least recently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰 2. volatile-lfu(least frequently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰 3. volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰 4. volatile-random:从已设置过期
Redis的数据持久化策略有哪些 ?
Redis 提供了两种方式,实现数据的持久化到硬盘。 1. RDB 持久化(全量),是指在指定的时间间隔内将内存中的数据集快照写入磁盘。 2. AOF持久化(增量),以日志的形式记录服务器所处理的每一个写、删除操作 RDB和AOF一起使用, 在Redis4.0版本支持混合持久化方式 ( 设置 aof-use-rdb-preamble yes )
Redis压测脚本及持久化机制
Redis压测脚本及持久化机制简介: Redis性能压测通过`redis-benchmark`工具进行,可评估读写性能。持久化机制包括无持久化、RDB(定期快照)和AOF(操作日志),以及两者的结合。RDB适合快速备份与恢复,但可能丢失数据;AOF更安全,记录每次写操作,适合高数据安全性需求。两者结合能兼顾性能与安全性,建议同时开启并定期备份RDB文件以确保数据安全。
110 9
Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
通过本文的介绍,我们详细讲解了 Lua 脚本在 Redis 中的作用、`eval` 命令的使用方法以及 `redis.call` 和 `redis.pcall` 的区别和用法。通过合理使用 Lua 脚本,可以实现复杂的业务逻辑,确保操作的原子性,并减少网络开销,从而提高系统的性能和可靠性。
228 13
Redis的数据过期策略有哪些 ?
1. 惰性删除 :只会在取出 key 的时候才对数据进行过期检查。这样对 CPU 最友好,但是可能会造成太多过期 key 没有被删除。数据到达过期时间,不做处理。等下次访问该数据时,我们需要判断 a. 如果未过期,返回数据 b. 发现已过期,删除,返回nil 2. 定期删除 : 每隔一段时间抽取一批 key 执行删除过期 key 操作。并且,Redis 底层会通过限制删除操作执行的时长和频率来减少删除操作对 CPU 时间的影响。默认情况下 Redis 定期检查的频率是每秒扫描 10 次,用于定期清除过期键。当然此值还可以通过配置文件进行设置,在 redis.conf 中修改配置“hz”
|
8月前
|
公司用什么软件监控电脑:Lua 脚本在监控软件扩展功能的应用
在企业环境中,电脑监控软件对保障信息安全、提升效率至关重要。Lua 脚本在此类软件中用于扩展功能,如收集系统信息、监控软件使用时长及文件操作,向指定服务器发送数据,支持企业管理和运营。
132 6
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
427 0
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
127 2
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等