17、Redis-Cell限流算法

学习目标:

1、了解限流算法

2、了解Redis-Cell的限流的使用

学习过程:

一、redis-cell命令

有很多业务场景需要做限流,比如有些论坛一分钟只能发表10份文章,如果每一次都要获得当前时间,再去数据库查询,效率是非常慢的,Redis提供了一个外部模块redis-cell,可以非常简单的实现限流。和bloom filter布隆过滤器一样需要额外安装。先登陆官网网址

https://github.com/brandur/redis-cell

因为redis-cell是使用rust语言编写,所以这里我们就不下载源码包了,直接下载编译后的版本,找到对应的操作系统的版本即可,里面有一个so文件,和bloom filter布隆过滤器再redis.conf中添加该模块,

vim /etc/redis.conf

loadmodule /usr/local/redis/module/rediscell/libredis_cell.so

保存退出就可以了,然后重启redis服务即可。

该模块只有一个命令,查看官方的说明:

CL.THROTTLE user123 15 30 60 1
               ▲     ▲  ▲  ▲ ▲
               |     |  |  | └───── apply 1 token (default if omitted)
               |     |  └──┴─────── 30 tokens / 60 seconds
               |     └───────────── 15 max_burst
               └─────────────────── key "user123"

user123 就是key
15 是max_burst,就是初始时,最大的容量,就是令牌桶初始时的数量,但是初始化数量是该值加一。
400: 与下一个参数一起,表示在指定时间窗口内允许访问的次数
30 和 60 就是速率,表示每60秒可以有30个令牌数量
1:最后一个表示本次要申请的令牌数,不写则默认为 1。

我们先执行一下命令

127.0.0.1:6379> CL.THROTTLE user123 15 30 60 1
1) (integer) 0   # 0 表示允许,1表示拒绝
2) (integer) 16  # 漏斗总容量 就是 15+1得到的。
3) (integer) 15  # 漏斗剩余空间,取得了一个所以剩下15
4) (integer) -1  # 如果拒绝了,需要多长时间后再试(漏斗有空间了,单位秒)
5) (integer) 2  # 表示多久后令牌桶中的令牌会存满(单位秒)

我们可以继续执行

127.0.0.1:6379> CL.THROTTLE user123 15 30 60 5
1) (integer) 0
2) (integer) 16
3) (integer) 11
4) (integer) -1
5) (integer) 10
127.0.0.1:6379> CL.THROTTLE user123 15 30 60 5
1) (integer) 0
2) (integer) 16
3) (integer) 7
4) (integer) -1
5) (integer) 17
127.0.0.1:6379> CL.THROTTLE user123 15 30 60 5
1) (integer) 0
2) (integer) 16
3) (integer) 3
4) (integer) -1
5) (integer) 25
127.0.0.1:6379> CL.THROTTLE user123 15 30 60 5
1) (integer) 1
2) (integer) 16
3) (integer) 3
4) (integer) 2
5) (integer) 24

因为每60秒可以有30次,所以过两秒又可以了。发现后面就返回1了,等一下再次执行又可以了。

127.0.0.1:6379> CL.THROTTLE user123 15 30 60 2
1) (integer) 0
2) (integer) 16
3) (integer) 14
4) (integer) -1
5) (integer) 4

一、redis-cell命令的java实现

因为是扩展命令,所以要先继承ProtocolCommand扩展命令,代码如下:

public enum CellCommand implements ProtocolCommand {
	CLTHROTTLE("CL.THROTTLE");
    
    private final byte[] raw;
	CellCommand(String alt) {
        raw = SafeEncoder.encode(alt);
    }
    public byte[] getRaw() {
        return raw;
    }
}

运行代码

@Test
public void testCell() {
	Jedis jedis = new Jedis("192.168.137.101", 6379);
	jedis.auth("123456");
	Connection client = jedis.getClient();
	client.sendCommand(CellCommand.CLTHROTTLE, "user123", "15", "30", "60", "2");
	List<Long> replay = client.getIntegerMultiBulkReply();
	for(Long s:replay) {
		System.out.println(s);
	}
	client.close();
}

输出结果:

0
16
14
-1
4
 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值