本文已收录于专栏
❤️《Redis之大厂必备技能包》❤️
上千人点赞收藏的,全套Redis学习资料,大厂必备技能!
目录
1、简介
2、Redis-Cell的安装
2.1 GitHub源码&安装包
2.2 安装&异常处理
3、CL.THROTTLE指令
4、Java调用Redis-Cell模块实现限流
4.1 导入依赖
4.2 实现代码
1、简介
令牌桶算法比较简单,它就好比摇号买房,拿到号的人才有资格买,没拿到号的就只能等下次了(还好小编不需摇号,因为买不起!)。
在实际的开发中,系统会维护一个容器用于存放令牌(token),并且系统以一个固定速率往容器中添加令牌(token),这个速率通常更加系统的处理能力来权衡。当客户端的请求打过来时,需要从令牌桶中获取到令牌(token)之后,这个请求才会被处理,否则直接拒绝服务。
令牌桶限流的关键在于发放令牌的速率和令牌桶的容量。实现令牌桶限流的方式有很多种,本文讲述的是基于Redis的Redis-Cell限流模块,这是Redis提供的适用于分布式系统、高效、准确的限流方式,使用十分广泛,而且非常简单!
2、Redis-Cell的安装
Redis默认是没有集成Redis-Cell这个限流模块的,就好比Redis使用布隆过滤器一样,我们也需要对该模块进行安装与集成。
2.1 GitHub源码&安装包
Redis-Cell的GitHub地址:
https://github.com/brandur/redis-cell
Redis-Cell基于Rust语言开发,如果不想花费精力去搞Rust环境,那么可以直接下载与你的操作系统对应的安装包(这个很关键,我就安装了挺多次的,如果安装的问题比较多的话,也建议降低一个release版本!)
- 如果重启Redis后,客户端无法连接成功,说明Redis启动失败,这个时候我们需要查看Redis的启动日志,如果已经配置日志文件的可以直接查看日志定位问题,如果还未配置日志文件的需要先配置日志文件,redis.conf添加日志文件路径地址,再次重启,查看日志文件输出的错误日志
43767:M 08 Sep 2021 21:39:39.643 # Module /usr/local/soft/Redis-Cell-0.3.0/libredis_cell.so failed to load: /lib64/libc.so.6: version `GLIBC_2.18' not found (required by /usr/local/soft/Redis-Cell-0.3.0/libredis_cell.so) 43767:M 08 Sep 2021 21:39:39.643 # Can't load module from /usr/local/soft/Redis-Cell-0.3.0/libredis_cell.so: server aborting
package com.lizba.redis.limit.tokenbucket; import io.lettuce.core.RedisClient; import io.lettuce.core.api.StatefulRedisConnection; import io.lettuce.core.dynamic.RedisCommandFactory; import java.util.List; /** * <p> * Redis-Cell令牌桶限流 * </p> * * @Author: Liziba * @Date: 2021/9/8 23:47 */ public class TokenBucketRateLimiter { private static final String SUCCESS = "0"; private RedisClient client; private StatefulRedisConnection<String, String> connection; private IRedisCommand command; public TokenBucketRateLimiter(RedisClient client) { this.client = client; this.connection = client.connect(); this.command = new RedisCommandFactory(connection).getCommands(IRedisCommand.class); } /** * 请是否被允许 * * @param key * @param maxBurst * @param tokens * @param seconds * @param apply * @return */ public boolean isActionAllowed(String key, long maxBurst, long tokens, long seconds, long apply) { List<Object> result = command.throttle(key, maxBurst, tokens, seconds, apply); if (result != null && result.size() > 0) { return SUCCESS.equals(result.get(0).toString()); } return false; } }