点击上方“芋道源码”,选择“设为星标”
管她前浪,还是后浪?
能浪的浪,才是好浪!
每天 10:33 更新文章,每天掉亿点点头发...
源码精品专栏
原创 | Java 2021 超神之路,很肝~
中文详细注释的开源项目
RPC 框架 Dubbo 源码解析
网络应用框架 Netty 源码解析
消息中间件 RocketMQ 源码解析
数据库中间件 Sharding-JDBC 和 MyCAT 源码解析
作业调度中间件 Elastic-Job 源码解析
分布式事务中间件 TCC-Transaction 源码解析
Eureka 和 Hystrix 源码解析
Java 并发源码
来源:业余草
Redis限流用法
基于Java的Redis限流用法
这个限流算法的缺点是什么
ChatGpt实现的短信发送Redis限流功能
本文的内容和源码都来自于 ChatGpt,大家感受一下 ChatGpt 的强大,比我写的都好!
Redis可以用来实现限流,其中比较常用的是基于令牌桶算法实现的限流方式。下面是一个基于Redis的令牌桶限流的实现示例:
首先需要在Redis中设置一个有序集合,用来存储令牌桶的令牌信息,比如令牌的数量、令牌的过期时间等。
当有请求需要进行限流时,先从Redis中获取令牌桶中的令牌数量,如果令牌数量不足,则返回限流失败。
如果令牌数量充足,则从令牌桶中消耗一个令牌,并更新令牌桶中的令牌数量和过期时间。
返回限流成功。
下面是一个基于Python的实现示例:
import redis
import time
class RedisRateLimiter:
def __init__(self, redis_conn, key, capacity, rate, default_timeout):
self.redis_conn = redis_conn
self.key = key
self.capacity = capacity
self.rate = rate
self.default_timeout = default_timeout
def is_allowed(self):
# 获取当前令牌桶中的令牌数量和过期时间
count, timestamp = self.redis_conn.zscore(self.key, 'tokens'), self.redis_conn.zscore(self.key, 'timestamp')
if count is None or timestamp is None:
# 如果令牌桶不存在,则创建一个新的令牌桶
self.redis_conn.zadd(self.key, { 'tokens': self.capacity, 'timestamp': time.time() })
count, timestamp = self.capacity, time.time()
# 计算应该有多少个令牌
delta = time.time() - timestamp
new_tokens = delta * self.rate
if new_tokens > 0:
# 更新令牌桶中的令牌数量和过期时间
self.redis_conn.zadd(self.key, { 'tokens': min(count + new_tokens, self.capacity), 'timestamp': time.time() })
# 判断令牌数量是否充足
count = self.redis_conn.zscore(self.key, 'tokens')
if count is None:
return False
elif count > 0:
# 消耗一个令牌
self.redis_conn.zadd(self.key, { 'tokens': count - 1 })
return True
else:
return False
这个实现中,redis_conn
是Redis
连接对象,key是存储令牌桶信息的有序集合的键名,capacity
是令牌桶的容量,rate是每秒钟生成的令牌数量,default_timeout
是令牌桶的默认过期时间。is_allowed()
方法用来判断当前请求是否允许通过,如果允许通过则返回True
,否则返回False
。
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/YunaiV/ruoyi-vue-pro
视频教程:https://doc.iocoder.cn/video/
好的,下面是基于Java的Redis限流用法示例:
首先需要添加Redis的Java客户端依赖,比如Jedis或Lettuce。以Jedis为例,可以在Maven项目中添加以下依赖:
redis.clients
jedis
3.6.3
在Java代码中实现令牌桶算法的限流逻辑。下面是一个基于Jedis的令牌桶限流的实现示例:
import redis.clients.jedis.Jedis;
public class RedisRateLimiter {
private Jedis jedis;
private String key;
private int capacity;
private double rate;
private int defaultTimeout;
public RedisRateLimiter(Jedis jedis, String key, int capacity, double rate, int defaultTimeout) {
this.jedis = jedis;
this.key = key;
this.capacity = capacity;
this.rate = rate;
this.defaultTimeout = defaultTimeout;
}
public boolean isAllowed() {
// 获取当前令牌桶中的令牌数量和过期时间
Double count = jedis.zscore(key, "tokens");
Double timestamp = jedis.zscore(key, "timestamp");
if (count == null || timestamp == null) {
// 如果令牌桶不存在,则创建一个新的令牌桶
jedis.zadd(key, timestamp, String.valueOf(System.currentTimeMillis() / 1000));
jedis.zadd(key, count, String.valueOf(capacity));
count = Double.valueOf(capacity);
timestamp = Double.valueOf(System.currentTimeMillis() / 1000);
}
// 计算应该有多少个令牌
double delta = System.currentTimeMillis() / 1000 - timestamp;
double newTokens = delta * rate;
if (newTokens > 0) {
// 更新令牌桶中的令牌数量和过期时间
jedis.zadd(key, timestamp + delta, String.valueOf(System.currentTimeMillis() / 1000));
jedis.zadd(key, count + newTokens, String.valueOf(capacity));
}
// 判断令牌数量是否充足
count = jedis.zscore(key, "tokens");
if (count == null) {
return false;
} else if (count > 0) {
// 消耗一个令牌
jedis.zadd(key, count - 1, "tokens");
return true;
} else {
return false;
}
}
}
这个实现中,jedis
是Jedis
客户端实例,key
是存储令牌桶信息的有序集合的键名,capacity
是令牌桶的容量,rate
是每秒钟生成的令牌数量,defaultTimeout
是令牌桶的默认过期时间。isAllowed()
方法用来判断当前请求是否允许通过,如果允许通过则返回true
,否则返回false
。
基于以上的方法,在短信发送时,进行限流。限制每个号码在的发生频率,限制每分钟的系统处理能力。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/YunaiV/yudao-cloud
视频教程:https://doc.iocoder.cn/video/
这个限流算法(令牌桶算法)的缺点主要有以下几点:
对于短时间内突发流量的处理不太友好。由于令牌桶算法是按照一定速率生成令牌,当请求流量超出了这个速率时,就会导致令牌桶中没有足够的令牌,此时请求会被限流。如果短时间内有大量请求同时到来,就会导致很多请求被限流,而令牌桶中的令牌也不足以应对这种情况。
令牌桶算法需要不断地更新令牌桶中的令牌数量和过期时间。这样就需要频繁地向Redis服务器发送写操作,增加了系统的负担,而且在高并发情况下可能会出现性能问题。
如果Redis服务器出现故障,可能会导致令牌桶中的令牌数量和过期时间不准确,从而影响限流效果。
令牌桶算法在限流时只能判断请求是否允许通过,而不能统计请求的具体数量。如果需要统计请求数量,需要结合其他算法,比如计数器算法。
综上所述,令牌桶算法在实际应用中需要根据具体场景选择合适的限流算法,避免上述缺点造成不良影响。
欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢:
已在知识星球更新源码解析如下:
最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。
提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。
获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)