IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Redis-Cell令牌桶限流详述 -> 正文阅读

[大数据]Redis-Cell令牌桶限流详述

本文已收录于专栏

??《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)之后,这个请求才会被处理,否则直接拒绝服务。
令牌桶限流的关键在于发放令牌的速率和令牌桶的容量。

令牌桶限流.png

实现令牌桶限流的方式有很多种,本文讲述的是基于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版本!)

image.png

下载对应的安装包:

https://github.com/brandur/redis-cell/releases/download/v0.3.0/redis-cell-v0.3.0-armv7-unknown-linux-gnueabihf.tar.gz

image.png

如果不清楚自己的服务器(Linux)版本的,可以事先查看后再下载安装包:

#?Linux?查看当前操作系统的内核信息
uname?-a
#?查看当前操作系统系统的版本信息
cat?/proc/version

image.png

2.2 安装&异常处理

  • 在Redis的安装目录的同级目录下,新建文件夹Redis-Cell,将压缩包上传后解压
tar?-zxvf?redis-cell-v0.2.5-powerpc64-unknown-linux-gnu.tar.gz
  • 解压后出现如下文件,复制libredis_cell.so文件的路径(pwd查看当前路径

image.png

  • 修改Redis配置文件,redis.conf,添加完成后记得保存后再退出

image.png

  • 重启Redis,如果启动正常,进入redis客户端,通过module list查看挂载的模块是否有Redis-Cell

image.png

  • 测试指令,出现如下情况说明集成Redis-Cell成功

image.png

  • 如果重启Redis后,客户端无法连接成功,说明Redis启动失败,这个时候我们需要查看Redis的启动日志,如果已经配置日志文件的可以直接查看日志定位问题,如果还未配置日志文件的需要先配置日志文件,redis.conf添加日志文件路径地址,再次重启,查看日志文件输出的错误日志

image.png

  • 错误可能千奇百怪,问题不大搞技术就不要心急,一个个解决,我这里记录下我最后遇到的问题,/lib64/libc.so.6: version `GLIBC_2.18‘ not found
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
  • 缺失GLIBC_2.18,那就安装它(最后两个编译的过程时间比较长,耐心等待几分钟)
yum?install?gcc
wget?http://ftp.gnu.org/gnu/glibc/glibc-2.18.tar.gz
tar?zxf?glibc-2.18.tar.gz?
cd?glibc-2.18/
mkdir?build
cd?build/
../configure?--prefix=/usr
make?-j4
make?install
  • 安装完成后,重启Redis,测试是否安装成功,循环上面的过程,通过日志分析错误即可

3、CL.THROTTLE指令

指令CL.THROTTLE参数含义

CL.THROTTLE?liziba??10??5?60?1
???????????????▲?????▲??▲??▲?▲
???????????????|?????|??|??|?└─────?apply?1?token?(default?if?omitted)?(本次申请一个token)
???????????????|?????|??└──┴───────?5?tokens?/?60?seconds??(60秒添加5个token到令牌桶中)
???????????????|?????└─────────────?10?max_burst????(最大的突发请求,不是令牌桶的最大容量)
???????????????└───────────────────?key?"liziba"?(限流key)

输出参数值含义

127.0.0.1:6379>?cl.throttle?liziba?10?5?60?1
1)?(integer)?0????????????????????#?当前请求是否被允许,0表示允许,1表示不允许
2)?(integer)?11????????????????????#?令牌桶的最大容量,令牌桶中令牌数的最大值
3)?(integer)?10??????????????????#?令牌桶中当前的令牌数
4)?(integer)?-1????????????????????#?如果被拒绝,需要多长时间后在重试,如果当前被允许则为-1
5)?(integer)?12????????????????????#?多长时间后令牌桶中的令牌会满

这里唯一有歧义的可能是max_burst,这个并不是令牌桶的最大容量,从作者的README.md中的解释也可以看出来

The total limit of the key (max_burst + 1). This is equivalent to the common X-RateLimit-Limit HTTP header.

image.png

4、Java调用Redis-Cell模块实现限流

4.1 导入依赖

<dependency>
??<groupId>io.lettuce</groupId>
??<artifactId>lettuce-core</artifactId>
??<version>5.3.4.RELEASE</version>
??<!--排除?netty?包冲突-->
??<exclusions>
????<exclusion>
??????<groupId>io.netty</groupId>
??????<artifactId>netty-buffer</artifactId>
????</exclusion>
????<exclusion>
??????<groupId>io.netty</groupId>
??????<artifactId>netty-common</artifactId>
????</exclusion>
????<exclusion>
??????<groupId>io.netty</groupId>
??????<artifactId>netty-codec</artifactId>
????</exclusion>
????<exclusion>
??????<groupId>io.netty</groupId>
??????<artifactId>netty-transport</artifactId>
????</exclusion>
??</exclusions>
</dependency>

4.2 实现代码

Redis命令接口定义:

package?com.lizba.redis.limit.tokenbucket;

import?io.lettuce.core.dynamic.Commands;
import?io.lettuce.core.dynamic.annotation.Command;

import?java.util.List;

/**
?*?<p>
?*??????Redis命令接口定义
?*?</p>
?*
?*?@Author:?Liziba
?*?@Date:?2021/9/8?23:50
?*/
public?interface?IRedisCommand?extends?Commands?{


????/**
?????*?定义限流方法
?????*
?????*?@param?key???????????限流key
?????*?@param?maxBurst??????最大的突发请求,桶容量等于maxBurst?+?1
?????*?@param?tokens????????tokens?与?seconds?是组合参数,表示seconds秒内添加个tokens
?????*?@param?seconds???????tokens?与?seconds?是组合参数,表示seconds秒内添加个tokens
?????*?@param?apply?????????当前申请的token数
?????*?@return
?????*/
????@Command("CL.THROTTLE??0??1??2??3??4")
????List<Object>?throttle(String?key,?long?maxBurst,?long?tokens,?long?seconds,?long?apply);

}

Redis-Cell令牌桶限流类定义:

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;
????}

}

测试代码:

package?com.lizba.redis.limit.tokenbucket;

import?io.lettuce.core.RedisClient;

/**
?*?<p>
?*??????测试令牌桶限流
?*??????测试参数?cl.throttle?liziba?10?5?60?1
?*?</p>
?*
?*?@Author:?Liziba
?*?@Date:?2021/9/9?0:02
?*/
public?class?TestTokenBucketRateLimiter?{

????public?static?void?main(String[]?args)?{
????????RedisClient?client?=?RedisClient.create("redis://192.168.211.108:6379");
????????TokenBucketRateLimiter?limiter?=?new?TokenBucketRateLimiter(client);
????????//?cl.throttle?liziba?10?5?60?1
????????for?(int?i?=?1;?i?<=?15;?i++)?{
????????????boolean?success?=?limiter.isActionAllowed("liziba",?10,?5,?60,?1);
????????????System.out.println("第"?+?i?+?"次请求"?+?(success???"成功"?:?"失败"));
????????}

????}

}

测试结果(这里也说明了令牌桶的容量是max_burst + 1):

第0次请求成功
第1次请求成功
第2次请求成功
第3次请求成功
第4次请求成功
第5次请求成功
第6次请求成功
第7次请求成功
第8次请求成功
第9次请求成功
第10次请求成功
第11次请求成功
第14次请求失败
第15次请求失败
第14次请求失败
第15次请求失败
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-09-10 10:55:57  更:2021-09-10 10:56:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:44:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码