⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 业余草 「业余草」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

ChatGpt实现的短信发送Redis限流功能

本文的内容和源码都来自于 ChatGpt,大家感受一下 ChatGpt 的强大,比我写的都好!

Redis限流用法

Redis可以用来实现限流,其中比较常用的是基于令牌桶算法实现的限流方式。下面是一个基于Redis的令牌桶限流的实现示例:

  1. 首先需要在Redis中设置一个有序集合,用来存储令牌桶的令牌信息,比如令牌的数量、令牌的过期时间等。
  2. 当有请求需要进行限流时,先从Redis中获取令牌桶中的令牌数量,如果令牌数量不足,则返回限流失败。
  3. 如果令牌数量充足,则从令牌桶中消耗一个令牌,并更新令牌桶中的令牌数量和过期时间。
  4. 返回限流成功。

下面是一个基于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_connRedis连接对象,key是存储令牌桶信息的有序集合的键名,capacity是令牌桶的容量,rate是每秒钟生成的令牌数量,default_timeout是令牌桶的默认过期时间。is_allowed()方法用来判断当前请求是否允许通过,如果允许通过则返回True,否则返回False

基于Java的Redis限流用法

好的,下面是基于Java的Redis限流用法示例:

  1. 首先需要添加Redis的Java客户端依赖,比如Jedis或Lettuce。以Jedis为例,可以在Maven项目中添加以下依赖:

<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.6.3</version>
</dependency>

  1. 在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;
}
}
}

这个实现中,jedisJedis客户端实例,key是存储令牌桶信息的有序集合的键名,capacity是令牌桶的容量,rate是每秒钟生成的令牌数量,defaultTimeout是令牌桶的默认过期时间。isAllowed()方法用来判断当前请求是否允许通过,如果允许通过则返回true,否则返回false

基于以上的方法,在短信发送时,进行限流。限制每个号码在的发生频率,限制每分钟的系统处理能力。

这个限流算法的缺点是什么

这个限流算法(令牌桶算法)的缺点主要有以下几点:

  1. 对于短时间内突发流量的处理不太友好。由于令牌桶算法是按照一定速率生成令牌,当请求流量超出了这个速率时,就会导致令牌桶中没有足够的令牌,此时请求会被限流。如果短时间内有大量请求同时到来,就会导致很多请求被限流,而令牌桶中的令牌也不足以应对这种情况。
  2. 令牌桶算法需要不断地更新令牌桶中的令牌数量和过期时间。这样就需要频繁地向Redis服务器发送写操作,增加了系统的负担,而且在高并发情况下可能会出现性能问题。
  3. 如果Redis服务器出现故障,可能会导致令牌桶中的令牌数量和过期时间不准确,从而影响限流效果。
  4. 令牌桶算法在限流时只能判断请求是否允许通过,而不能统计请求的具体数量。如果需要统计请求数量,需要结合其他算法,比如计数器算法。

综上所述,令牌桶算法在实际应用中需要根据具体场景选择合适的限流算法,避免上述缺点造成不良影响。

文章目录
  1. 1. Redis限流用法
  2. 2. 基于Java的Redis限流用法
  3. 3. 这个限流算法的缺点是什么