参考文章: https://www.jianshu.com/p/1b026b874c40?from=timeline&isappinstalled=0
(1)下载安装包 https://github.com/brandur/redis-cell/releases
(2)解压到某个目录
(3)进入 redis-cli,执行命令module load /aaa/bbb/libredis_cell.so 这是临时的办法,重启redis就没了
(4)想永久的,需要这样 $ redis-server --loadmodule /aaa/bbb/libredis_cell.so 加到启动命令里。
(5)进入 redis-cli,执行命令,可以看看是否生效。 127.0.0.1:6379> command info CL.THROTTLE 1) 1) "cl.throttle" 2) (integer) -1 3) 1) write 4) (integer) 1 5) (integer) 1 6) (integer) 1 127.0.0.1:6379> MODULE LIST 1) 1) "name" 2) "redis-cell" 3) "ver" 4) (integer) 1
(6)然后不停的执行类似这样的命令就行了: CL.THROTTLE test 10 5 60 1 初始是10个令牌,每60秒允许5个。 多执行几次,就返回1拒绝了。
127.0.0.1:6379> CL.THROTTLE test 10 5 60 1 1) (integer) 0 2) (integer) 11 3) (integer) 4 4) (integer) -1 5) (integer) 0
1: 是否成功,0:成功,1:拒绝 2: 令牌桶的容量,大小为初始值+1 3: 当前令牌桶中可用的令牌 4: 若请求被拒绝,这个值表示多久后才令牌桶中会重新添加令牌,单位:秒,可以作为重试时间 5: 表示多久后令牌桶中的令牌会存满 ================================================= java中调用~~ (1)pom引入lettuce
<dependency> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> <version>5.2.0.RELEASE</version> </dependency>
注意,它会引入netty的一些包,如果你已经有netty了,注意排除,以免冲突。
(2)写一个command接口
package com.xxx.util;
import java.util.List;
import io.lettuce.core.dynamic.Commands; import io.lettuce.core.dynamic.annotation.Command;
public interface RedisCommandInterface extends Commands {
/** * 限流,如CL.THROTTLE test 10 5 60 1 * <p> * test是key名字,初始10个令牌,每60秒允许使用5个令牌,本次获取一个令牌 * <p> * 127.0.0.1:6379> CL.THROTTLE test 10 5 60 1 * <p> * 1) (integer) 0 0成功,1拒绝 * <p> * 2) (integer) 11 令牌桶的容量 * <p> * 3) (integer) 10 当前令牌桶中可用的令牌 * <p> * 4) (integer) -1 若请求被拒绝,这个值表示多久后才令牌桶中会重新添加令牌,单位:秒,可以作为重试时间 * <p> * 5) (integer) 12 表示多久后令牌桶中的令牌会存满 * * @param name * @param initCapactiy * @param operationCount * @param secondCount * @param getCount * @return */ @Command("CL.THROTTLE ?0 ?1 ?2 ?3 ?4") List<Object> throttle(String key, long initCapactiy, long operationCount, long secondCount, long getCount); }
(3)然后调用即可
package com.xxx.util;
import java.util.List;
import io.lettuce.core.RedisClient; import io.lettuce.core.api.StatefulRedisConnection; import io.lettuce.core.dynamic.RedisCommandFactory;
public class RedisUtil {
private static RedisClient redisClient = null; private static StatefulRedisConnection<String, String> conn = null; private static RedisCommandInterface commands; private static long initCapactiy = 20; private static long operationCount = 20; private static long secondCount = 1; private static long getCount = 1;
static {
// 创建连接(会自动重连) redisClient = RedisClient.create("redis://xxxx@127.0.0.1:6379/0"); conn = redisClient.connect();
// 获取Command RedisCommandFactory factory = new RedisCommandFactory(conn); commands = factory.getCommands(RedisCommandInterface.class); }
public static boolean isAllowQuery(String name) {
//最多等两次 for(int i=0;i<3;i++) { List<Object> resultList = commands.throttle(name, initCapactiy, operationCount, secondCount, getCount);
if (resultList.get(0).toString().equals("0")) { return true; } //睡半秒 try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
System.out.println("fail,"+name); return false;
// Luna脚本不认这个命令 // RedisCommands<String, String> cmds = conn.sync(); // List<String> resultList = cmds.eval(" return redis.call('CL.THROTTLE test 10 // 5 60 1') ",ScriptOutputType.MULTI); //
}
}
(4)简单粗暴~~
|