博客
关于我
Redis 限流的 3 种方式,还有谁不会?
阅读量:802 次
发布时间:2023-03-06

本文共 2063 字,大约阅读时间需要 6 分钟。

面对越来越多的高并发场景,限流显示的尤为重要。限流是一种核心的流量管理机制,旨在在单位时间内限制系统的吞吐量,避免服务器过载或服务失效。本文将介绍Redis在限流中的三种主要实现方式,并分析其优缺点。

第一种:基于Redis的SetNX操作

Redis的SetNX命令(Set if Not Exists)在限流中被广泛使用。其基本原理是通过在指定的键中设置一个唯一的值(通常是一个随机的UUID),同时设置一个过期时间(Expire)。当单位时间内的请求数量达到预设的上限时,后续请求将被拒绝。

例如,假设我们希望在10秒内最多允许20个请求。SetNX操作会在Redis中创建一个键值对,键为“limit”,值为唯一的UUID,过期时间为10秒。当请求的数量达到20个时,系统将自动拒绝后续请求。这一方法实现起来相对简单,但存在一些明显的缺陷。

其主要缺点在于,当需要统计多个时间窗口(如1-10秒,2-11秒等)时,Redis的键会变得非常繁多,导致存储开销增加。此外,滑动窗口的实现需要额外的逻辑处理,才能确保计数的准确性。

第二种:基于Redis的数据结构ZSET

ZSET(有序集合)在限流中的应用主要体现在滑动窗口的实现上。滑动窗口的核心思想是记录当前窗口内的请求数量,并在每次请求到来时更新窗口的起始和结束时间。

具体实现方法是将每个请求的时间戳作为ZSET中的分数值(Score),请求自身的唯一标识作为ZSET的成员。通过查询ZSET中位于[currentTime - interval, currentTime]区间内的成员数量,可以快速得到当前窗口内的请求总数。

这种方法的优点在于实现简单且能够轻松支持复杂的滑动窗口逻辑。代码示例如下:

public Response limitFlow() {
Long currentTime = new Date().getTime();
if (redisTemplate.hasKey("limit")) {
Integer count = redisTemplate.opsForZSet().rangeByScore("limit", currentTime - intervalTime, currentTime).size();
if (count != null && count > 5) {
return Response.ok("每分钟最多只能访问5次");
}
}
redisTemplate.opsForZSet().add("limit", UUID.randomUUID().toString(), currentTime);
return Response.ok("访问成功");
}

然而,这一方法也存在一些问题。ZSET的数据量会随着时间的推移而不断增加,尤其是在高并发场景下,可能导致存储压力增大。

第三种:基于Redis的令牌桶算法

令牌桶算法是限流领域的经典方法之一,其核心思想是通过控制令牌的分发速度来限制系统的吞吐量。与前两种方法不同,令牌桶算法更关注输入和输出速率的平衡。

具体实现方式是使用Redis的列表(List)数据结构来存储令牌。每次请求时,系统尝试从列表中取出一个令牌(leftPop)。如果成功,说明请求被允许;如果失败,则表示超出限流限制。

代码示例如下:

public Response limitFlow2(Long id) {
Object result = redisTemplate.opsForList().leftPop("limit_list");
if (result == null) {
return Response.ok("当前令牌桶中无令牌");
}
return Response.ok(articleDescription2);
}

为了保持令牌的唯一性,定时任务会向列表中添加新的令牌。例如:

@Scheduled(fixedDelay = 10000, initialDelay = 0)
public void setIntervalTimeTask() {
redisTemplate.opsForList().rightPush("limit_list", UUID.randomUUID().toString());
}

这三种限流方式各有其优缺点。SetNX简单易行,但难以支持复杂的滑动窗口逻辑;ZSET能够轻松实现滑动窗口,但存在存储压力问题;令牌桶算法则更注重输入输出速率的平衡,但实现稍微复杂一些。

综上所述,选择合适的限流方式需要根据具体的业务需求和系统性能进行权衡。Redis不仅可以用于限流,还可以支持其他功能如数据统计、附近点查询等。未来可以进一步探索其其他应用场景。

转载地址:http://ooafk.baihongyu.com/

你可能感兴趣的文章
Redis 限流的 3 种方式,还有谁不会?
查看>>
Python这么慢,为啥大公司还在用?
查看>>
python note 06 编码方式
查看>>
python numba 转灰度图_使用NumPy、Numba的简单使用(二)
查看>>
Python Numpy 关于 linspace()函数 使用详解(全)
查看>>
Python numpy插入、读取至postgreSQL数据库中bytea类型字段
查看>>
Python numpy数据的保存和读取
查看>>
python numpy矩阵索引_python – 在2D numpy ndarray或numpy矩阵中获取前N个值的索引
查看>>
Python OCR库:自动化测试验证码识别神器!
查看>>
python opencv - 斑点检测或圆形检测
查看>>
Python还可以做情感分析你不看看吗?
查看>>
Python OpenCV HoughLinesP 无法检测线
查看>>
Python OpenCV-使用透明度覆盖图像
查看>>
python Opencv图像基础操作
查看>>
Python OpenCV将图像转换为字节字符串?
查看>>
python OpenCV视频的读取及保存
查看>>
python open和file的区别
查看>>
python open读取文件并对换行进行处理
查看>>
python os, os.path和sys模块
查看>>
Python os.environ 处理环境变量
查看>>