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

点击上方“芋道源码”,选择“设为星标

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 10:33 更新文章,每天掉亿点点头发...

源码精品专栏

 

来源:业余草


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

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

基于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

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

c7eadd5cdb4c7b2e8199b5d4838fdb70.png

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

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

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

  1. 对于短时间内突发流量的处理不太友好。由于令牌桶算法是按照一定速率生成令牌,当请求流量超出了这个速率时,就会导致令牌桶中没有足够的令牌,此时请求会被限流。如果短时间内有大量请求同时到来,就会导致很多请求被限流,而令牌桶中的令牌也不足以应对这种情况。

  2. 令牌桶算法需要不断地更新令牌桶中的令牌数量和过期时间。这样就需要频繁地向Redis服务器发送写操作,增加了系统的负担,而且在高并发情况下可能会出现性能问题。

  3. 如果Redis服务器出现故障,可能会导致令牌桶中的令牌数量和过期时间不准确,从而影响限流效果。

  4. 令牌桶算法在限流时只能判断请求是否允许通过,而不能统计请求的具体数量。如果需要统计请求数量,需要结合其他算法,比如计数器算法。

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



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

daaddf5138bae9efd10cbee25e0482d1.png

已在知识星球更新源码解析如下:

da55df9e1b9757bf784935bdf84d1cd6.jpeg

20ee0cfee86a420d22fd318fba4281d7.jpeg

371e486d42b7c719bbbfcfadea5be3da.jpeg

4dde6084d01506fe5bbae7a5c79420d2.jpeg

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis可以通过令牌桶算法、漏桶算法等多种算法实现限流功能,以下是其中一种实现方式: 1. 令牌桶算法实现限流 令牌桶算法是一种基于令牌的限流算法,其原理是在令牌桶中放入一定数量的令牌,每次请求需要从令牌桶中获取令牌才能被处理,当令牌桶中的令牌数量耗尽时,新的请求就会被限流实现步骤: 1)设置一个定时器,定时向令牌桶中添加令牌。 2)每次请求需要从令牌桶中获取令牌,如果令牌桶中没有足够的令牌,则限流。 3)实现代码: ```python import redis import time class RedisLimit: def __init__(self, host, port, password, limit, interval): self.limit = limit self.interval = interval self.redis_conn = redis.StrictRedis(host=host, port=port, password=password, db=0) def is_limit_exceeded(self, key): current_time = time.time() pipeline = self.redis_conn.pipeline() pipeline.multi() pipeline.zadd(key, current_time, current_time) pipeline.zremrangebyscore(key, 0, current_time - self.interval) pipeline.zcard(key) count, *_ = pipeline.execute() return count > self.limit if __name__ == '__main__': redis_host = 'localhost' redis_port = 6379 redis_password = '' key = 'redis_limit' limit = 100 interval = 60 # 1分钟内最多访问100次 redis_limit = RedisLimit(redis_host, redis_port, redis_password, limit, interval) for i in range(200): if redis_limit.is_limit_exceeded(key): print('Limit exceeded') else: print('Access granted') ``` 该代码中使用了Redis的有序集合(sorted set)数据结构来实现令牌桶算法,其中: - `zadd(key, current_time, current_time)`:向有序集合`key`中添加一个`current_time`的元素,并将其分值(score)设置为`current_time`。 - `zremrangebyscore(key, 0, current_time - self.interval)`:删除有序集合`key`中分值小于等于`current_time - self.interval`的元素。 - `zcard(key)`:返回有序集合`key`的元素个数。 2. 漏桶算法实现限流 漏桶算法是一种基于漏桶的限流算法,其原理是在一个固定容量的漏桶中不断地积累请求,每次请求会从漏桶中流出一定的容量,当漏桶中的容量耗尽时,新的请求就会被限流实现步骤: 1)设置一个定时器,定时从漏桶中流出一定的容量。 2)每次请求需要向漏桶中添加请求,如果漏桶已满,则限流。 3)实现代码: ```python import redis import time class RedisLimit: def __init__(self, host, port, password, limit, interval): self.limit = limit self.interval = interval self.redis_conn = redis.StrictRedis(host=host, port=port, password=password, db=0) def is_limit_exceeded(self, key): current_time = time.time() pipeline = self.redis_conn.pipeline() pipeline.multi() pipeline.zadd(key, current_time, current_time) pipeline.zremrangebyscore(key, 0, current_time - self.interval) pipeline.zcard(key) count, *_ = pipeline.execute() return count > self.limit if __name__ == '__main__': redis_host = 'localhost' redis_port = 6379 redis_password = '' key = 'redis_limit' limit = 100 interval = 60 # 1分钟内最多访问100次 redis_limit = RedisLimit(redis_host, redis_port, redis_password, limit, interval) for i in range(200): if redis_limit.is_limit_exceeded(key): print('Limit exceeded') else: print('Access granted') ``` 该代码中使用了Redis的有序集合(sorted set)数据结构来实现漏桶算法,其中: - `zadd(key, current_time, current_time)`:向有序集合`key`中添加一个`current_time`的元素,并将其分值(score)设置为`current_time`。 - `zremrangebyscore(key, 0, current_time - self.interval)`:删除有序集合`key`中分值小于等于`current_time - self.interval`的元素。 - `zcard(key)`:返回有序集合`key`的元素个数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值